一·我们举个必须要用重载运算符和重载运算符时必须要使用引用的例子
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;
}
输出:
constructor called
constructor called
string1
string1
destrustor called
destrustor called
这里我们重载了赋值运算符,将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是不允许的,编译器不允许临时对象调用成员函数。
因此这种情况必须要用引用来传递参数和返回参数,使用引用返回的参数可以作为左值。
以上为学习时做的笔记,借鉴于网上各路博客大神,有雷同很正常,欢迎各位同学指正。