当函数的参数是类的对象而非指针/引用时调用函数传递参数的过程就是值传递此时编译器会自动调用拷贝构造函数创建一个实参的“副本”作为函数的形参。一、值传递触发拷贝构造函数的完整过程可以把这个过程想象成“复制粘贴”1、你准备把一个已存在的对象实参传给函数2、因为是值传递函数不会直接使用原对象而是需要一个独立的副本3、编译器会调用该类的拷贝构造函数用原对象实参为模板创建一个新的对象形参4、函数内部操作的是这个“副本”函数执行完毕后副本会被销毁调用析构函数5、原对象不受函数内操作的影响二、代码示例12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849#include iostream#include stringusingnamespacestd;classPerson {public:string name;// 带参构造函数Person(string n) : name(n) {cout [构造] 创建对象 name endl;}// 拷贝构造函数核心值传递时会调用Person(constPerson other) {this-name other.name 副本;// 给副本加标记方便识别cout [拷贝构造] 为值传递创建副本this-name endl;}// 析构函数~Person() {cout [析构] 销毁对象 name endl;}// 成员函数修改名字仅影响副本voidchangeName(string newName) {this-name newName;cout [函数内] 修改副本名字为this-name endl;}};// 函数参数为值传递Person对象而非指针/引用voidtestValuePass(Person p) {p.changeName(修改后的副本);}intmain() {// 1. 创建原对象Person p1(原对象-张三);cout ------------------------ endl;// 2. 调用函数值传递参数 → 触发拷贝构造testValuePass(p1);cout ------------------------ endl;// 3. 查看原对象未被修改cout [主函数] 原对象名字 p1.name endl;return0;}控制台[构造] 创建对象原对象-张三------------------------[拷贝构造] 为值传递创建副本原对象-张三副本[函数内] 修改副本名字为修改后的副本[析构] 销毁对象修改后的副本------------------------[主函数] 原对象名字原对象-张三[析构] 销毁对象原对象-张三三、关键细节拆解1、触发时机执行testValuePass(p1)时编译器发现参数是值传递Person p立即调用Person(const Person other)拷贝构造函数的参数other就是原对象p1函数内创建的p是p1的副本。2、为什么必须是拷贝构造如果没有显式定义拷贝构造函数编译器会生成默认的浅拷贝构造函数依然会触发只是没有日志输出只有参数是const 类名的构造函数才是拷贝构造函数这是 C 的语法规则。3、对比避免拷贝构造的方式如果不想触发拷贝构造提升性能避免深拷贝开销可以把参数改成引用传递12345// 引用传递直接操作原对象不触发拷贝构造voidtestRefPass(Person p) {p.changeName(修改原对象);}调用testRefPass(p1)时不会调用拷贝构造函数函数内修改的是原对象p1。四、常见误区澄清×误区“值传递只是把对象的值复制过去和拷贝构造无关”√正解C 中类对象的 “值复制” 本质就是通过拷贝构造函数完成的这是面向对象的核心规则。五、总结1、触发条件函数参数为类对象值传递时编译器会自动调用拷贝构造函数创建实参的副本作为形参。2、过程本质值传递的 “复制” 拷贝构造函数的调用 新对象副本的创建。3、优化建议如果不需要修改原对象用const 类名const 引用传递参数既不触发拷贝构造又能防止函数内修改原对象。