背景:如果不提供,就是浅拷贝,即位拷贝(把值按字节复制过去)
位拷贝的危害:
1、比如某个类的对象当中有堆上的资源(里面有一个指针指向了堆上的资源)
2、文件句柄、socket
3、虚函数表指针可能会丢失
。。。如果是位拷贝,就会出现两个对象持有相同的堆上资源、文件句柄
如果有一个对象释放,释放时会把堆上资源进行释放,把文件句柄进行清空,另一个对象是通过位拷贝(浅拷贝)得来的,会持有相同的堆上资源、文件句柄,那它对应的数据操作文件的时候就会发生异常,比如操作堆上数据会报错
什么时候会触发拷贝构造函数?
a.赋值
A b;
1、A a(b);
2、A a=b;
b.函数传参,形参为类对象
c.函数返回值:
默认的时候,c++会开启编译器优化,通常称之为返回值优化
- A func(){
- A a;//如果有优化,只会调用这一次构造函数
- ...//基于a进行的一些操作
- return a;//如果去掉优化,(c++11)a就是一个将亡值
- }
-
- 可能有:
- A a=func();
- 去掉优化后,首先把函数中的a变成将亡值将亡值赋值给a时首先考虑的是移动构造,比如a(函数里的a)上有一些资源(堆上的资源、文件句柄、socket等),把这些资源移动给a的对象
如果去掉优化,c++11以上,
1、看类有没有移动构造
2、然后看类有没有拷贝构造
3、如果这两个都没有,就报错了
什么时候生成默认拷贝构造函数?
编译器编译的时候生成,为什么要生成,因为不得不生成(为了避免出现一些问题)(因为会和c++语法冲突,编译器要维护语法一致,所以需要再某些情况下不得不生成)
1、类成员变量也是一个类,该成员类有默认拷贝构造函数
- class A{
- private:
- B b;
- };
类B有默认的拷贝构造函数,所以再构造类A时为了能够调用类B的默认拷贝构造函数,A必须要构造一个拷贝构造函数
b.类继承自一个基类,该基类(父类)有默认拷贝构造函数(也是为了能够调用到父类的拷贝构造函数,必须生成一个)
c.类成员中有一个或多个虚函数(防止浅拷贝)(避免虚函数表指针丢失)
d.类继承自基类,基类中有虚函数