C++有一种特殊的构造函数叫做复制构造函数,允许所创建的对象是另一个对象的精确副本。如果没有编写,编译器将自动生成一个。利用源对象相应数据成员的值初始化新对象的每个数据成员。
#include <iostream> using namespace std; class A { private: int i; string str; public: A(int ii,string s):i(ii),str(s){ } /* A(const A &a){//为了提高效率,一般参数使用引用,并且使用const保证不改变原来的值 cout<<"before copy ,i="<<i<<",str="<<str<<endl; //这一句间接说明了int类型如果不赋初始值时其值时不确定的,取决于当时内存中的值 i=a.i; str=a.str; cout<<"复制函数已经调用"<<endl; } */ A(const A &a):i(a.i),str(a.str){ //最好使用初始化器的方式初始化 cout<<"复制函数已经调用"<<endl; } void show()const{ cout<<"i="<<i<<",str="<<str<<endl; cout<<"address:&i="<<&i<<",&str="<<&str<<endl<<endl; } }; int main() { A a(10,"hello"); cout<<"this is a:"<<endl; a.show(); cout<<"this is b:"<<endl; A b(a); b.show(); cout<<"this is c:"<<endl; A c=b;//注意,这一个调用的也是复制构造函数,而不是赋值构造函数 //类似于声明的语句会调用复制构造函数,原因时A c=b;c当时还没创建,是不会调用operator=方法的。 c.show(); }
运行结果:
但有一点要注意的就是,如果构造函数体内有数据成员是使用new来分配空间的话,如果不手动编写复制构造函数,就会出错!
#include <iostream> #include <cstring> using namespace std; class A { private: char *str; public: A(const char *s){ int len=sizeof(s);
//因为是赋值构造函数,所以在this对象中还没有str,因此不用delete []str; str=new char[len+1]; strcpy(str,s); } //不定义复制构造函数 //让编译器自动生成一个 ~A(){ cout<<"start delete!"<<endl; delete []str; cout<<"delete complete!"<<endl; } void show()const{ cout<<"str="<<str<<endl; cout<<"address:&str="<<&str<<endl<<endl; } }; int main() { { A a("hello"); cout<<"this is a:"<<endl; a.show(); cout<<"this is b:"<<endl; A b(a); b.show(); cout<<"this is c:"<<endl; A c=b;//注意,这一个调用的也是复制构造函数,而不是赋值构造函数 //类似于声明的语句会调用复制构造函数,原因时A c=b;c当时还没创建,是不会调用operator=方法的。 c.show(); } }
运行结果:
看似似乎a,b,c的地址都不一样,一开始我也很疑惑。但是在gdb下面调试发现其实并不是这样。
而且运行的时候也提示了两次free了同一内存。看析构中的输出也可以分析出是在free中出现了问题。
用GDB调试查看:
可以看出,实际上str地址都是一样的。都是指向同一个内存单元0X603010,而&a.str的地址都不相同。难道是说&a.str是指存放这个变量地址的地址?似乎只有这样才能说的通。使用p a.str查看,果然如此。
C++11同样提供了显式默认或者删除复制构造函数。方法和默认构造函数一致。
显式默认复制构造函数。
A(const A &a)=default;
显式删除复制构造函数
A(const A &a)=delete;
这样,编译器就将禁止使用复制构造函数。编译结果:
还有一种方法就是利用移动语义以及右值引用,这里由于我也不是和熟练,就先不写了。
——————————————————————————————————————————————————
//写的错误或者不好的地方请多多指导,可以在下面留言或者给我发邮件,指出我的错误以及不足,以便我修改,更好的分享给大家,谢谢。
转载请注明出处:https://www.royalchen.com/
author:royalchen
Email:royalchen@royalchen.com
———————————————————————————————————————————————————