1.拷贝构造函数是与类名相同,其形参是本类的对象的引用。
2.拷贝构造函数会在以下三种情况下被调用:
1).当用类的一个对象去初始化该类的另一个对象时。
2).如果函数的形参是类的对象,调用该函数,将对象作为函数实参传递给函数的形参时。
3).如果函数的返回值是类的对象,函数执行完成,将返回值返回时。
3.浅拷贝的失败例子:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 #include <iostream> 2 #include <cstring> 3 4 using namespace std; 5 6 7 class str 8 { 9 private: 10 char *s; 11 int len; 12 public: 13 str() 14 { 15 len=0; 16 s=NULL; 17 } 18 str(const char *p) 19 { 20 len=strlen(p); 21 s=new char[len+1]; 22 strcpy(s,p); 23 } 24 ~str() 25 { 26 if(s!=NULL) 27 { 28 delete []s; 29 s=NULL; 30 } 31 } 32 }; 33 34 int main() 35 { 36 str s1("I love you!"); 37 str s2=s1; //这里会发生错误。 38 return 0; 39 }
之所以发生错误是因为两个对象在析构时都要delete那块堆里的内存,但是程序里是浅拷贝,也就是说,s2只拷贝了s1的堆内存的地址,s2的s指针指向s1申请的堆内存,两次delete同一块内存,明显不合法。故而需要增加自定义拷贝构造函数,即深拷贝。见于下例:
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
1 str(str &r) 2 { 3 len=r.len; 4 if(len!=0) 5 { 6 s=new char[len+1]; 7 strcpy(s,r.s); 8 } 9 }
4.注意:
1).在自定义拷贝构造函数后,缺省拷贝构造函数和构造函数失效,构造函数需要自定义。
2).在自定义构造函数后,缺省构造函数失效,但缺省拷贝构造函数仍有效。