调用拷贝构造函数的几种情况
当类中成员有指针变量、类中有动态内存分配时常常需要用户自己定义拷贝构造函数。
在什么情况下系统会调用拷贝构造函数:
(1)用类的一个对象去初始化另一个对象时
(2)当函数的形参是类的对象时(也就是值传递时),如果是引用传递则不会调用
(3)当函数的返回值是类的对象或引用时
代码示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| class Test { public: int a; Test(int i):a(i) { cout<<a<<'\t' << "构造函数" << endl; } ~Test() { cout<<a<<'\t' << "析构函数"<<endl; } Test(const Test &b) { a = b.a; cout << b.a <<'\t'<< "拷贝构造函数" << endl; } };
int main() { Test a(10); Test b(20); Add(a, b); }
|
调用函数为值传递
1 2 3 4 5
| Test Add(Test a, Test b) { auto res = Test(a.a + b.a); return res; }
|
输出为
| 输出 |
解释 |
| 10 构造函数 |
|
| 20 构造函数 |
a,b初始化 |
| 20 拷贝构造函数 |
|
| 10 拷贝构造函数 |
形参的拷贝构造,右到左 |
| 30 构造函数 |
Test(a.a + b.a)临时对象 |
| 30 拷贝构造函数 |
赋值给res |
| 30 析构函数 |
Test(a.a + b.a)临时对象析构 |
| 10 析构函数 |
|
| 20 析构函数 |
形参析构 |
| 30 析构函数 |
返回值res的析构函数 |
| 20 析构函数 |
|
| 10 析构函数 |
a,b析构函数 |
参数为引用传递
1 2 3 4 5
| Test Add(Test& a, Test& b) { auto res = Test(a.a + b.a); return res; }
|
| 输出 |
解释 |
| 10 构造函数 |
|
| 20 构造函数 |
a,b 初始化 |
| 30 构造函数 |
Test(a.a + b.a)临时变量初始化 |
| 30 拷贝构造函数 |
res的复制构造(值传递) |
| 30 析构函数 |
临时对象析构 |
| 30 析构函数 |
res析构 |
| 20 析构函数 |
|
| 10 析构函数 |
a,b析构 |
返回值为引用
1 2 3 4 5
| Test& Add(Test& a, Test& b) { auto res = Test(a.a + b.a); return res; }
|
| 输出 |
解释 |
| 10 构造函数 |
|
| 20 构造函数 |
|
| 30 构造函数 |
res 是 临时对象的引用,因此不会拷贝构造 |
| 30 析构函数 |
|
| 20 析构函数 |
|
| 10 析构函数 |
|