定义:使用类的一个对象来构造和初始化另一个对象,这另一个对象之前是不存在的。
要注意理解拷贝(复制)和赋值的区别,拷贝和复制时另一个对象之前是不存在的,而赋值是两个对象都构造好了。
如:A a; A b(a); A b = a; 这是拷贝
A a; A b; b = a;这是赋值
拷贝构造函数的重载声明如下:
A(const A& other)
举例:
class A
{
private:
int m_i;
public:
A()
{
}
A(const A&other):m_i(other.m_i)
{
}
};
在C++中,下列三种情况下对象需要调用拷贝构造函数:
1)一个对象以值传递的方式传入函数体;
2)一个对象以值传递的方式从函数返回;
3)一个对象需要通过另一个对象进行初始化。
如果在前两种情况下不使用拷贝构造函数,就会导致一个指针指向已经被删除的内存空间(这句话尚未完全理解,待详解)。
浅拷贝与深拷贝
如果一个类拥有资源(比如指针),在这个类的对象发生拷贝的时候,如果没有重新分配资源,就是浅拷贝;如果重新分配了资源,就是深拷贝。什么意思呢,举个例子:
class Array
{
private:
int m_iCount;
int *m_pArr;
public:
Array()
{
m_iCount = 10;
m_pArr = new int[m_iCount];
}
Array(const Array& other)
{
m_iCount = other.m_iCount;
m_pArr = other.m_pArr;
}
};
int main()
{
Array arr1;
Array arr2 = arr1; //调用拷贝构造函数
return 0;
}
上述代码就是一个浅拷贝,但存在什么问题呢,Array的拷贝构造函数没有给拷贝对象重新分配内存,arr1.m_pArr和arr2.m_pArr指向的是同一块内存,当arr1被析构时,arr1.m_pArr指向的内存就被释放了,这时arr2.m_pArr指向的内存就不存在了,相应的arr2.m_pArr就变成了野指针。在实际的编程设计中要避免浅拷贝,使用深拷贝。什么是深拷贝呢,改变上面代码的拷贝构造函数如下:
Array(const Array& other)
{
m_iCount = other.m_iCount;
m_pArr = new int[m_iCount];
for(int i=0;i<m_iCount;i++)
{
m_pArr[i] = other.m_pArr[i];
}
}