举个必须要用重载运算符和重载运算符时必须要使用引用的例子
class Myclass { private: char* str; public: Myclass( char* str1 = "default string" ) { str = new char[strlen( str1 ) + 1]; strcpy( str, str1 ); cout << "constructor called" << endl; } ~Myclass() { cout << "destrustor called" << endl; } void showChar() { cout << str << endl; } Myclass &operator = (const Myclass &ele) { delete[] str; str = new char[strlen( ele.str ) + 1]; strcpy( str, ele.str ); return(*this); } }; int main() { Myclass class1( "string1" ); Myclass class2; class2 = class1; class1.showChar(); class2.showChar(); return(0); }
这里我们重载了赋值运算符,将class1的str赋给了class2.str;
若我们不重载赋值运算符,用原来自带的‘=’,则会调用复制构造函数,将class1的str的值复制给class2的str,这是两个str指向统一内存。在程序完成时,调用析构函数,先调用class2的析构函数,把str所指向的内存给清除,完成后再调用class1的析构函数,由于在class2时已经把str所指向的内存给清除了,这时会出现内存泄漏。
为什么这里的重载赋值运算符一定要用引用?
若参数不用引用,则有Myclass &operator=(const Myclass ele) {
这时实参传值给形参会创建一个临时变量,调用复制构造函数将实参复制给形参,实参的str与形参的str指向同一块内存。所以,当赋值函数完成时,会清除函数的所占的内存,形参就会被清除,形参的str指向的内存也就会被清除。再调用class1.showchar()会发现内存泄漏。
输出结果如下:
constructor called
constructor called
䁷䁷䁷䁷䁷
string1
destrustor called
destrustor called
若重载运算符函数的返回类型不用引用,则有则有Myclass operator=(const Myclass &ele) {
这是返回对象时会创建一个临时对象,再调用复制构造函数,将返回的对象复制给临时对象,函数结束后,返回的对象被清除,返回对象的str所指向的内存也被清除,由于返回对象和临时对象的 str指向同一块内存,所以calss2=class1的str指向一块随机内存,在调用class2.showchar()时会随机输出。
输出结果如下:
constructor called
constructor called
string1
䁷䁷䁷䁷䁷
destrustor called
destrustor called
此外:
(class2=class1)=class3是不允许的,编译器不允许临时对象调用成员函数。
0 条评论