首页 > 代码库 > 关于复制构造函数的几个问题

关于复制构造函数的几个问题

一、什么是复制构造函数

  复制构造函数是一种特殊的构造函数,其形参是本类对象的引用,作用是完成同类对象之间的复制。一般情况下编译器生成一个默认的复制构造函数不需要我们考虑,但有些情况下,默认的复制构造函数无法提供完整的功能,这时就需要我们自己来编写实现。复制构造函数形式如下:

//假如类名是Test
class Test
{
public:
  Test(){}
    /*复制构造的形参是通过引用传递的,
因为如果不用引用就是使用值传递,
会调用复制构造函数,形成一个矛盾!
*/   Test(
const Test& src)   {     a = src.a;     b = src.b   }   ~Test(){} private:   int a;   float b; };

 

二、哪些情况调用了复制构造函数

Test a;     // 调用构造函数
Test b = a; // 调用复制构造函数
Test c(a);  // 调用复制构造函数

// 函数形式参数为对象本身(非指针或引用)
void func(Test _a){...}
func(a);

// 函数返回值为对象本身
Test func(){...}
Test a;
a = func();

 

三、什么时候需要自己编写复制构造函数

 根据三五法则,当你的析构函数不为空时就应当自己编写复制构造函数。

看下面这个例子

 1 //test.h
 2 class Test
 3 {
 4 public:
 5     Test()
 6     {
 7         p = new int(1);
 8         cout << "constructor: "<<*p << endl;
 9     }
10     Test(const Test& src)
11     {
12         p = new int(1);
13         *p = *(src.p);
14         cout <<"copy constructor: "<< *p << endl;
15 
16     }
17 
18     const Test& operator=(const Test& src)
19     {
20         p = new int;
21         *p = *(src.p);
22         cout << "operator" << endl;
23         return *this;
24     }
25     ~Test()
26     {
27         delete p;
28         cout << "deconstructor: " <<endl;
29     }
30 
31 private:
32     int* p;
33 };
34 
35 //test.cpp
36 int main()
37 {
38     Test a;
39     Test b = a;
40     a = b;
41     vector<Test> v;
42     //push_back两个对象下面就会报错!Why??
43     v.push_back(b);
44     v.push_back(a);
45 
46     auto it = v.begin();
47      v.erase(it);
48     return 0;
49     cout << v.size() << endl;
50 
51     return 0;
52 }

 

四、重载赋值运算符

 上面的程序中有一个坑,当vector删除元素时调用erase函数,其中可能会在内部调用赋值运算符;而默认的赋值运算符也不能满足需求(原理同复制构造函数),所以我们不仅要编写复制构造函数还要重载赋值运算符。

1 const Test& operator=(const Test& src)
2 {
3     ...
4     //内容同复制构造函数
5     ...
6     return *this;
7 }

 

总结

当析构函数不为空时,一定要编写好复制构造函数,并重载赋值运算符!你永远不知道什么时候就用到它们了。。。

关于复制构造函数的几个问题