值传递时形参是实参的独立副本,编译器通过拷贝构造或位拷贝创建新对象,内存地址与生命周期均与实参无关,故函数内修改不影响原变量;如swap(int a,int b)无法交换实参x、y。

值传递时形参只是实参的副本
因为 int、double、自定义结构体等非引用/指针类型传入函数时,编译器会调用拷贝构造(或位拷贝)生成一个**独立的新对象**,它和原始变量内存地址不同、生命周期独立。函数内对这个副本的任何修改,自然不影响外部原变量。
常见错误现象:以为改了,其实没变
比如写了一个交换函数:
void swap(int a, int b) {
int tmp = a;
a = b;
b = tmp;
}调用 swap(x, y) 后,x 和 y 的值完全不变——因为函数里操作的是 a 和 b 这两个临时副本。
- 调试时发现变量值没变,但函数逻辑看起来“应该”改了
- 返回值也没用,因为函数没返回新值,也没通过其他途径传出
- 结构体较大时还可能因重复拷贝导致性能下降
怎么真正修改外部变量?选对传参方式
有三种主流办法,适用场景不同:
立即学习“C++免费学习笔记(深入)”;
- 用指针:
void swap(int* a, int* b),调用时传&x、&y;缺点是调用方要显式取地址,且需检查空指针 - 用非 const 引用:
void swap(int& a, int& b),调用时直接传x、y;最接近“原地修改”的直觉,但不能传字面量或临时对象(比如swap(5, x)会编译失败) - 返回新值并由调用方赋值:
std::pair<int> swap(int a, int b) { return {b, a}; }</int>,再写auto [x, y] = swap(x, y);;适合函数本就该产出新状态的场景
容易被忽略的细节:const 引用也能避免拷贝,但不能改
如果只是想读大对象(比如 std::vector<int>),又不想拷贝,用 const std::vector<int>& v 是安全且高效的;但它明确禁止修改,所以别指望靠它“绕过值传递限制来修改”。一旦需要写,就必须去掉 const 或换指针。
另外,类类型若禁用了拷贝构造(如 std::unique_ptr),值传递会直接编译失败——这时候连“副本”都造不出来,更凸显必须主动选引用或指针。


















