C++:拷贝构造函数 📅 2026/7/4 3:34:45 一、什么是拷贝构造函数拷贝构造函数是一种特殊的构造函数它的参数是同类型对象的常量引用即用已存在的一个变量初始化另一个同类型变量。classPerson{public:// 拷贝构造函数Person(constPersonother){nameother.name;ageother.age;cout拷贝构造被调用endl;}// 其他...private:string name;intage;};二、拷贝构造函数的语法规则函数名与类名相同。没有返回值。参数必须是同类型对象的引用通常为 const 。可以自定义也可以让编译器自动生成。classMyClass{public:// 拷贝构造函数的典型形式MyClass(constMyClassother);};为什么参数要写引用如果类没有管理动态资源比如没有 new 分配内存我们其实只需要把原对象的值复制给新对象就够了。那能不能直接把原对象的值当作普通参数传给拷贝构造函数让它用这个值来初始化新对象呢答案是不行原因在于C规定传值传参必须调用拷贝构造。而我们若在实现拷贝构造时使用传值传参则又会生成新的拷贝构造如此不断生成新的拷贝构造最后会造成死循环。三、何时调用拷贝构造函数用一个对象初始化另一个对象Personp1(Alice,25);Person p2p1;// 调用拷贝构造Personp3(p1);// 调用拷贝构造函数参数按值传递voidfunc(Person p){...}func(p1);// 实参p1拷贝给形参p调用拷贝构造函数按值返回对象Personcreate(){Persontemp(Bob,30);returntemp;// 返回值时可能调用拷贝构造或移动语义}容器中的元素插入当容器需要复制元素时会调用拷贝构造。如 vector 的 push_back四、默认拷贝构造函数编译器自动生成的拷贝构造如果类中没有定义拷贝构造函数编译器会自动生成一个它执行浅拷贝shallow copy逐个复制成员变量的值。什么时候需要自己写拷贝构造当类中有指针成员并指向动态分配的内存时浅拷贝会导致两个对象共享同一块内存应该为新对象申请一块新的内存需要自己手动实现若执行浅拷贝则会直接释放时会产生重复释放或内存泄漏。classShallow{public:int*data;Shallow(intval){datanewint(val);}// 编译器生成的默认拷贝构造data other.data浅拷贝};intmain(){Shallowa(10);Shallow ba;// 两个对象的data指向同一块内存// 析构时会重复释放导致未定义行为。}五、深拷贝自定义拷贝构造函数为了正确复制包含动态资源的对象我们需要自定义拷贝构造函数执行深拷贝deep copy申请一块新的空间再复制原指针指向的内容。classDeep{int*data;public:Deep(intval){datanewint(val);}// 深拷贝构造Deep(constDeepother){datanewint(*other.data);// 重新分配并复制值}~Deep(){deletedata;}};intmain(){Deepa(10);Deep ba;// 深拷贝各自拥有独立内存// 安全销毁}六、拷贝构造与赋值运算符的区别拷贝构造用已有对象初始化新对象对象尚未创建。赋值运算符将已有对象的值赋给已存在的对象对象已创建。Personp1(Alice,25);Person p2p1;// 拷贝构造p2尚未创建Personp3(Bob,30);p3p1;// 赋值运算符p3已存在七、禁止拷贝如果类不希望被复制可以显式删除拷贝构造函数C11classNonCopyable{public:NonCopyable()default;NonCopyable(constNonCopyable)delete;// 禁止拷贝};八、如何使用如果有资源的申请分配一般要自己实现。如果自定义了析构函数、拷贝构造、拷贝赋值其中之一通常需要自定义其他每个。优先使用深拷贝当类管理动态内存时务必实现深拷贝。用 const 引用避免不必要的拷贝提高性能。使用移动语义C11减少拷贝开销适合临时对象。九、完整示例#includeiostream#includecstringusingnamespacestd;classString{char*buf;public:String(constchar*s){bufnewchar[strlen(s)1];strcpy(buf,s);}// 拷贝构造深拷贝String(constStringother){bufnewchar[strlen(other.buf)1];strcpy(buf,other.buf);cout拷贝构造endl;}~String(){delete[]buf;}voidshow()const{coutbufendl;}};intmain(){Strings1(Hello);String s2s1;// 调用拷贝构造s1.show();s2.show();return0;}十、总结拷贝构造函数控制对象如何被复制是类设计的重要一环。浅拷贝适合简单类管理资源的类需要深拷贝。编译器默认生成拷贝构造但自定义更灵活、更安全。