C++搞懂深拷贝初始化=与赋值(运算符重载)=的区别
C++构造函数用=与()不完全一样,注意使用=时c++中临时变量不能作为非const的引用参数,不论是=运算符重载还是构造函数,否则可能出现以下错误
具体可以参考《C++ prime plus第六版》360页
代码
今天在学习右值引用时,遇到了深拷贝问题,以前也知道深拷贝与浅拷贝的区别,今天的疑问是,为什么不用重载=操作符在初始化时实现深拷贝,与赋值时=号的区别。
#include <iostream>
#include <functional>
using namespace std;
class Test
{
private:
int *data;
int s_size;
public:
Test(size_t size):s_size(size){
data=new int[s_size];
cout<<data<<endl;
}
Test(Test & t){//②
data=new int[t.s_size];
cout<<"&&&"<<data<<endl;
}
void operator=(const Test t){
if(t.data==nullptr){
cout<<"error"<<endl;
return;
}
if(data!=nullptr){
delete [] data;
}
data=new int[t.s_size];
cout<<"====="<<endl;
}
void data_addr(){
cout<<data<<endl;
}
void output(int x, int y)
{
cout << "x: " << x << ", y: " << y << endl;
}
int m_number = 100;
~Test(){
delete [] data;
}
};
int main(int argc,char *argv[])
{
cout<<1<<endl;
Test t(100);//调用有参构造函数
cout<<2<<endl;
Test b=t;//调用类引用构造函数
b.data_addr();
cout<<3<<endl;
Test c(b);//调用类引用构造函数
c.data_addr();
cout<<4<<endl;
Test d(200);//调用有参构造函数
cout<<5<<endl;
b.data_addr();
cout<<6<<endl;
d=b;//调用=号重载函数
d.data_addr();
cout<<7<<endl;
b.data_addr();
return 0;
}
运行结果:
结论
采用=号初始化时,如2,若没有复制构造函数,还采用编译器自带的等号进行浅拷贝,编写了复制构造函数后,如②,不论是=还是()达到的效果都是深拷贝。而赋值时的=号,如5,若没有重载=操作符的函数则是编译器自带的等号进行浅拷贝,编写了=号操作符的函数后,如②达到深拷贝。这两个在调用时不会混乱,一个就是初始化,一个就是赋值。而且在编写参数时,最好使用引用调用,否则会产生错误,因为同一内存被多次析构。
复制构造函数的参数不允许出现类的类型
把②去掉后的输出:
如果没有拷贝赋值函数(运算符重载=)则运行编译器自带的浅拷贝赋值函数;
采用值传递的方式则调用编写的复制构造函数,深拷贝。