因为c语言函数参数默认值传递,传指针时传递的是指针变量的副本,交换指针本身(如a和b)只改变局部副本地址,不修改实参指向的内存值;正确做法是解引用 a和 b,直接读写目标变量内存。

为什么直接传指针不能交换变量值
很多人写 swap 函数时,以为只要把地址传进去,函数里用 *a 和 *b 交换就行——结果发现调用完原变量没变。问题出在:函数参数本身是值传递的指针变量,a 和 b 在函数内只是两个新拷贝的地址值,交换它们(比如 int* temp = a; a = b; b = temp;)只改了局部指针,不影响实参指针所指向的内容。
正确做法:解引用后交换内存中的值
必须操作指针指向的内存位置,而不是指针本身。核心就是用 *a 和 *b 读写目标变量的值:
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
调用时传入变量地址:swap(&x, &y);。注意这要求两个指针都非空,否则解引用会触发未定义行为(如段错误)。
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
- 确保传入的是有效地址,比如局部变量、堆分配内存,不能是
nullptr - 类型必须严格匹配,
int*不能传double*,否则*a解引用会按错误字节长度读取 - 不适用于 const 变量,因为
*a = ...是写操作,而const int* a禁止修改所指内容
和 std::swap 的区别在哪
标准库的 std::swap 是模板函数,底层确实也靠解引用实现,但它支持任意可赋值类型,还做了优化(如对 POD 类型可能用 memcpy)。你自己写的指针版只能处理特定类型,且没做空指针检查或异常安全处理。
-
std::swap(x, y)直接传变量,不用手动取地址;你写的版本必须显式写&x、&y - 如果你写
std::swap(&x, &y),那是在交换两个指针变量本身的值,不是它们指向的内容——这是常见误用 - 自定义版本无法自动推导类型,
swap(&a, &b)中a和b必须同类型,否则编译失败
交换结构体或类对象时要注意什么
用指针交换结构体变量,本质还是交换内存块,但要注意对齐和构造/析构:
struct Person { int age; char name[20]; };
Person p1 = {25, "Alice"}, p2 = {30, "Bob"};
swap(&p1, &p2); // 这里 swap 必须是 Person* 版本
- 如果结构体含指针成员(如
char*),单纯 memcpy 级交换会导致浅拷贝问题——两个对象指向同一块动态内存 - 含非平凡析构函数或移动语义的类,用裸指针交换可能绕过正确资源管理,应优先用
std::swap或移动赋值 - 大小超过缓存行(通常 64 字节)的大对象,指针交换虽快,但后续访问可能因 cache miss 反而慢
真正需要手动指针交换的场景很少,多数时候直接用 std::swap 更安全;非要自己写,就得盯住类型、有效性、生命周期这三个点。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










