踩坑代码如下:
#include <iostream>
using namespace std;
class MyInteger {
friend ostream& operator<<(ostream& cout, MyInteger& myint);
private:
int num;
public:
MyInteger() {
num = 0;
}
MyInteger operator++(int) {
MyInteger temp = *this;
num++;
return temp;
}
};
//坑:传入MyInteger时使用了引用
ostream& operator<<(ostream& cout, MyInteger& myint) {
cout << myint.num;
return cout;
}
void func2() {
MyInteger mint;
//此时第一个左移运算符报错
cout << mint++ << endl;
}
int main() {
func2();
return 0;
}
附报错截图:
在以上代码,在定义类的左移运算时,传入MyInteger& mint 时使用了引用,导致在func2中输出时报错。
后来看到这篇博客,找到问题点。https://blog.csdn.net/Rejective/article/details/108709226
于是我做了以下测试:
...
//将后置递增的返回值,修改为返回临时对象的指针。显而易见,当该成员函数执行完毕后,指针指向的地址被释放。
MyInteger* operator++(int) {
MyInteger temp = *this;
num++;
return &temp;
}
...
void func2() {
MyInteger mint;
//定义一个指针来接收返回值
MyInteger *p = mint++;
cout << *p << endl; //0
cout << *p << endl; //32763
cout << *p << endl; //32763
//cout<< mint++ << endl;
}
可以看到*p后面两次输出的值已经不是我们预期的值,此时该指针指向的地址已经被释放。
而此时我们预期是执行后面这行被注释的代码,在自定义的左移函数中,传入的是一个引用,但是在此时mint++执行后返回值的地址已经被释放,因此在执行左移运算符时报错。
ostream& operator<<(ostream& cout, MyInteger& myint)
解决办法
ostream& operator<<(ostream& cout, MyInteger myint)
(PS:不要忘记在类声明友元出也做修改。)
传入参数时,不使用引用。
此时当参数传入,会通过MyInteger类的拷贝构造函数拷贝出一个对象副本,该对象生命周期为整个operator<<函数,直到函数执行完毕被释放。