什么是拷贝构造函数及拷贝构造函数的应用?
什么是拷贝构造函数
每个类都有6个默认成员函数(构造函数,析构函数,拷贝构造函数,赋值重载函数,取地址运算符重载函数,const修饰的取地址运算符重载函数)
也就是说即使你创建一个空类,也会存在这6个函数
其中构造函数只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰)
在用已存在的类类型对象创建新对象时由编译器自动调用
class solu {
int a;
public:
solu(int x) :
a(x)
{
}
};
int main()
{
solu a(5);
solu b(a); //此时调用拷贝构造函数
return 0;
}
拷贝构造函数的特征
- 拷贝构造函数是构造函数的一个重载形式。
- 拷贝构造函数的参数只有一个且必须使用引用传参,使用传值方式会引发无穷递归调用。
什么是浅拷贝?
- c++默认的拷贝构造函数是浅拷贝
浅拷贝就是对象的数据成员之间的简单赋值,如你设计了一个没有类而没有提供它的复制构造函数,当用该类的一个对象去给令一个对象赋值时所执行的过程就是浅拷贝,例如
class A
{
public:
A(int _data) : data(_data){}
A(){}
private:
int data;
};
int main()
{
A a(5), b = a; // 仅仅是数据成员之间的赋值
}
浅拷贝会导致什么结果?
如果拷贝对象中有对其他资源(如堆、文件、系统等)的引用(引用可以是指针或引用)
浅拷贝在复制对象时,只是简单的值复制,即两个对象共用一段内存区域
这是比较危险的。如果一个对象析构函数回收了这段内存,另外一个对象在执行析构函数时也会对这段内存进行回收,会导致一段内存被释放两次,这是非法操作,会导致程序崩溃
如何避免这个问题呢?这时我们就需要用到深拷贝
什么是深拷贝?
- 深拷贝指的就是当拷贝对象中有对其他资源(如堆、文件、系统等)的引用时(引用可以是指针或引用)时,对象的另开辟一块新的资源,而不再对拷贝对象中有对其他资源的引用的指针或引用进行单纯的赋值
class A
{
public:
A(int _size) : size(_size)
{
data = new int[size];
} // 假如其中有一段动态分配的内存
A(){};
A(const A& _A) : size(_A.size)
{
data = new int[size];
} // 深拷贝
~A()
{
delete [] data;
} // 析构时释放资源
private:
int* data;
int size;
}
int main()
{
A a(5), b = a; // 这次就没问题了
}
深拷贝和浅拷贝的区别
- 在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的;但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象,所以,此时,必须采用深拷贝。
- 深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来储存数据,从而也就解决了指针悬挂的问题。简而言之,当数据成员中有指针时,必须要用深拷贝。