我明白我应该回归“ostream&”来自“operator<<”能够像这样“链接”运营商
cout<<a<<b<<c;
但是,在下面的代码中,我没有返回“ostream&amp;”链接仍然是可能的。为什么呢?
#include <iostream>
using namespace std;
class CComplexNumber{
float m_realPart;
float m_imagPart;
public:
CComplexNumber(float r,float i):m_realPart(r),m_imagPart(i){}
friend ostream& operator<<(ostream& lhs,CComplexNumber rhs){
lhs<<"["<<rhs.m_realPart<<","<<rhs.m_imagPart<<"]"<<endl;
//MISSING RETURN STATEMENT!
}
};
int main() {
CComplexNumber a(1,2);
CComplexNumber b(3,4);
CComplexNumber c(5,6);
cout<<a<<b<<c;
return 0;
}
输出
[1,2]
[3,4]
[5,6]
答案 0 :(得分:8)
非空函数的结束是未定义的行为。一种可能的未定义行为正如您所希望的那样正常工作。
g ++提供了一个方便的警告,以防止这种情况发生在你身上。
答案 1 :(得分:3)
正如其他人所指出的,你已经调用了未定义的行为:任何事情都可能发生。如果你很幸运,你会崩溃。看起来你不幸运。
如果您对在这种情况下发生的原因感兴趣,您应该查看生成的程序集。我的袖口猜测是指向lhs
的指针留在寄存器中,返回平台上的值。而且由于C ++中的引用通常使用指针实现,这与将引用返回lhs
具有相同的效果。
但这是在黑暗中完全刺伤,最终不是很有趣或重要。只需听取编译器的警告,不要那样做。
答案 2 :(得分:1)
这是“纯粹的运气”。函数的返回值位于特定寄存器中。由于您现有的代码已经调用了operator<<
,因此它会为您返回正确的内容,因此只要在该点之后没有其他代码,您就会从{{1}的内部级别获得返回值。 }。添加operator<<
(并在代码中的某处使用std::string s = "xyz";"
),它可能会中断,因为在函数末尾调用的s
的析构函数“销毁”了返回值std::string
。所以依靠这是非常危险的,因为无害的变化会导致它“摔倒”。