为何拷贝类实例时赋值运算符重载未被调用,却执行两次拷贝构造?
为什么
DeepCopy dest2 = dest1;调用拷贝构造而非赋值运算符? 核心原因:这是初始化,不是赋值
C++里的=符号有两种完全不同的语义:
- 赋值操作:针对已经存在的对象。比如你先定义
DeepCopy dest2;,再写dest2 = dest1;,这时候才会触发你重载的赋值运算符。 - 拷贝初始化:当你在定义对象的同时用
=给它赋初始值(比如DeepCopy dest2 = dest1;),本质是在创建新对象,属于初始化行为,编译器会调用拷贝构造函数,而非赋值运算符。
为什么注释赋值重载还能编译?
如果你没自定义赋值运算符,C++编译器会自动生成一个默认的赋值运算符(浅拷贝版本)。所以即使你注释掉自己写的重载代码,只要代码里没触发浅拷贝问题的场景(比如类里没有动态分配的内存),编译器生成的默认版本就能正常工作,程序自然能编译运行。
关于“两次拷贝构造”的疑问
你提到DeepCopy dest1(source);和DeepCopy dest2 = dest1;都执行了两次拷贝构造,大概率是以下两种情况:
- source是临时对象或函数返回值:如果
source是通过返回DeepCopy对象的函数得到的,早期C++标准里,函数返回对象会触发一次拷贝构造(创建临时对象),再用临时对象初始化dest1又触发一次。不过现代编译器会通过**返回值优化(RVO)**合并这两次拷贝,若关闭了编译器优化,可能还能看到两次调用。 - 测试输出的混淆:可能你把
source自身的构造输出和拷贝构造的输出混在一起了。实际上DeepCopy dest1(source);应该只触发一次拷贝构造(从source拷贝到dest1),建议仔细核对输出对应的对象创建逻辑。
内容的提问来源于stack exchange,提问作者rebecca73
相关产品推荐
相关产品推荐

