C++拷贝构造函数调用疑问:为何第三种方式未触发显式实现?
关于拷贝构造函数与赋值运算符的疑问
问题详情
我测试了三种涉及对象拷贝的操作:
Test t2 = t1; // 方式1 Test t3(t1); // 方式2 Test t4; // 方式3 t4 = t1;
我显式定义的拷贝构造函数会将原对象的每个数据成员加10,前两种方式能正常调用该构造函数并执行加10操作,但第三种方式没有执行加10操作,看起来用了隐式的拷贝逻辑。
测试代码
#include <iostream> using namespace std ; class Test { int m,n ; public: Test() ; Test(int,int) ; ~Test() ; Test(Test&) ; void showData() ; } ; inline Test::Test(Test& t) { cout<<"called"<<endl ; m = t.m + 10 ; n = t.n + 10 ; } inline Test::Test(){} inline Test::Test(int m,int n) { Test::m = m ; Test::n = n ; } inline Test::~Test(){} inline void Test::showData() { cout<<m<<" "<<n<<endl ; } int main() { Test t1(3,4) ; t1.showData() ; Test t2(t1) ; t2.showData() ; Test t3 = t1 ; t3.showData() ; Test t4 ; // 调用隐式逻辑 t4 = t1 ; t4.showData() ; return 0 ; }
程序输出
3 4 called 13 14 called 13 14 3 4
我已经通过重载赋值运算符解决了第三种方式的问题,但想知道:为什么已经显式定义了拷贝构造函数,第三种方式还是没触发它,反而用了隐式逻辑?
问题解答
核心原因是这两种操作的本质完全不同:
- 前两种方式属于对象初始化:
Test t2(t1)是直接初始化,Test t3 = t1是拷贝初始化,二者都会触发拷贝构造函数,用来创建一个新对象并以已有对象为模板完成初始化,所以会执行你自定义的加10逻辑。 - 第三种方式是赋值操作:
t4 = t1是在t4已经被默认构造函数创建完成后,把t1的值拷贝给t4,这个过程触发的是赋值运算符,而非拷贝构造函数。
C++规则中,只要你没有显式重载赋值运算符,编译器会自动为类生成一个默认赋值运算符,这个默认函数只会做简单的成员逐值拷贝(也就是你观察到的“隐式逻辑”),不会复用拷贝构造函数里的自定义逻辑。
所以哪怕你定义了拷贝构造函数,也不会影响默认赋值运算符的生成和调用,这就是第三种方式没触发你自定义逻辑的根本原因。
内容的提问来源于stack exchange,提问作者M.B.
相关产品推荐
相关产品推荐

