C++允许将一个对象的值赋给另一个对象。
或许你认为这就是复制,然而,“复制”只在初始化对象的时候发生。
如果一个已经具有值的对象被改写了,那么更准确的来说就是“赋值”。
注意,C++提供的复制工具是复制构造函数,因为这是一个构构造函数,因此只能在对象创建的时候使用,而不能用在对象的赋值。
C++为所有的类提供了赋值工具,这个方法叫做赋值运算符,名称为operator=,实际上其实就是重载了=运算符。
例子:
#include <iostream> #include <cstring> using namespace std; class A { private: char *str; public: A(const char *s){ int len=sizeof(s); str=new char[len+1]; strcpy(str,s); } //删除复制构造函数 A(const A &a)=delete; ~A(){ cout<<"start delete!"<<endl; delete []str; cout<<"delete complete!"<<endl; } A &operator=(const A &a){//赋值运算符 if(this==&a)//注意检测是否是自赋值 return *this; int len=sizeof(a.str); delete []str;//重新分配str的内存 str=new char[len+1]; strcpy(str,a.str); cout<<"完成对象赋值"<<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("world"); b.show(); b=a;//对象赋值 b.show(); /* cout<<"this is c:"<<endl; A c=b;//注意,这一个调用的也是复制构造函数,而不是赋值构造函数 //类似于声明的语句会调用复制构造函数,原因时A c=b;c当时还没创建,是不会调用operator=方法的。 c.show(); */ } }
结果:
可以看到,执行
b=a;//对象赋值
这一句的时候用到了赋值运算符。
如果没有定义赋值运算符,C++编译器会自动生成一个类似于默认复制构造函数行为的赋值运算符。
需要注意的是要注意检测自赋值的这种情况。
还有一种情况就是:
#include <iostream> #include <cstring> using namespace std; class A { private: char *str; public: A(const char *s){ int len=sizeof(s); str=new char[len+1]; strcpy(str,s); } //删除复制构造函数 A(const A &a)=delete; ~A(){ cout<<"start delete!"<<endl; delete []str; cout<<"delete complete!"<<endl; } A &operator=(const A &a){//赋值运算符 if(this==&a)//注意检测是否是自赋值 return *this; int len=sizeof(a.str); delete []str;//重新分配str的内存 str=new char[len+1]; strcpy(str,a.str); cout<<"完成对象赋值"<<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("world"); b.show(); b=a;//对象赋值 b.show(); */ cout<<"this is c:"<<endl; A c=a;//注意,这一个调用的也是复制构造函数,而不是赋值构造函数 //类似于声明的语句会调用复制构造函数,原因时A c=b;c当时还没创建,是不会调用operator=方法的。 c.show(); } }
编译结果:
这说明了 A c=a;调用的不是赋值运算符而是复制构造函数。如何区分呢?
一般来说,类似于声明的使用的是复制构造函数,类似于赋值的使用的是赋值运算符。
当然,C++11也允许显式默认和删除赋值运算符,规则和复制构造和默认构造一样。
——————————————————————————————————————————————————
//写的错误或者不好的地方请多多指导,可以在下面留言或者给我发邮件,指出我的错误以及不足,以便我修改,更好的分享给大家,谢谢。
转载请注明出处:https://www.royalchen.com/
author:royalchen
Email:royalchen@royalchen.com
———————————————————————————————————————————————————