对于非内部类对象的赋值,会存在一个默认的赋值运算符重载函数。
如下面的代码中,c2=c1这句中调用了类A的默认的赋值运算符重载函数,实现了c2.real=c1.real; c2.image=c1.image;
class A{ private: int real; int image; public: A(int r,int i) { real=r; image=i; } }; int main() { A c1(1,2); A c2(0,0); c2=c1; }
- 那么赋值运算符重载函数 显式定义的时机是什么?
当类成员变量中有动态分配的存储空间时,需要显式定义。否则会出现与浅拷贝同样的问题,c1给c2赋值后,c1和c2中的指针指向同一个内存空间,析构时,同一个空间被析构两次,出现运行错误。 - 赋值运算符重载函数与拷贝构造函数的不同之处?(例子如下代码)
1)赋值运算符重载函数需要先释放对象自身空间原来的内容,再根据赋值对象c1的动态申请的内存空间大小,给c2动态申请同样大小的空间,再进行赋值;
拷贝构造函数只需要直接根据c1中的动态申请的内存大小,给c2动态申请同样大小的空间,进行赋值,不需要对c2先释放,因为c2还没初始化呢,拷贝构造函数是在c2初始化时调用的,A c2=c1;
2)调用时机不同,拷贝构造函数在初始化时调用,赋值运算只在赋值时调用。
拷贝构造函数和赋值运算符重载:class A{ private: char *name; char *namep; public: A(A& a1) { if(a1.name) { name=new char[strlen(a1.name)+1]; strcpy(name,a1.name); } if(a1.namep) { namep=new char[strlen(a1.namep)+1]; strcpy(namep,a1.namep); } } A &operator =(A &a1) { if(name) delete []name; if(namep) delete []namep; if(a1.name) { name=new char[strlen(a1.name)+1]; strcpy(name,a1.name); } else name=NULL; if(a1.namep) { namep=new char[strlen(a1.namep)+1]; strcpy(namep,a1.namep); } else namep=NULL; return *this; } };
- 赋值运算符重载函数的形参讨论;
赋值运算符的形参通常是本类对象的引用,因为对象的占用内存可能较大,使用本类对象引用,省去了临时对象所需的栈空间。同时不调用拷贝构造函数,也省去了拷贝的时间。
当然为了避免形参的值被改变,加const限定引用。因此形参为本类对象的 常引用。const A& a1; - 赋值运算符重载函数返回值讨论:
返回值可以是:void型返回,本类对象返回,本类对象的引用返回;
1)返回void型。赋值能够正常进行,但是因为没有返回值,那么赋值表达式不能连续赋值。
2)返回本类对象。会在返回时创建临时对象,调用拷贝构造函数初始化临时对象,函数结束后,临时对象会被析构;
3)返回本类对象的引用。不需要初始化内存临时对象,返回值是对象本身,即*this。