运算符的返回值<<功能

时间:2013-07-30 17:31:28

标签: c++

我明白我应该回归“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]

3 个答案:

答案 0 :(得分:8)

非空函数的结束是未定义的行为。一种可能的未定义行为正如您所希望的那样正常工作。

g ++提供了一个方便的警告,以防止这种情况发生在你身上。

答案 1 :(得分:3)

正如其他人所指出的,你已经调用了未定义的行为:任何事情都可能发生。如果你很幸运,你会崩溃。看起来你不幸运。

如果您对在这种情况下发生的原因感兴趣,您应该查看生成的程序集。我的袖口猜测是指向lhs的指针留在寄存器中,返回平台上的值。而且由于C ++中的引用通常使用指针实现,这与将引用返回lhs具有相同的效果。

但这是在黑暗中完全刺伤,最终不是很有趣或重要。只需听取编译器的警告,不要那样做。

答案 2 :(得分:1)

这是“纯粹的运气”。函数的返回值位于特定寄存器中。由于您现有的代码已经调用了operator<<,因此它会为您返回正确的内容,因此只要在该点之后没有其他代码,您就会从{{1}的内部级别获得返回值。 }。添加operator<<(并在代码中的某处使用std::string s = "xyz";"),它可能会中断,因为在函数末尾调用的s的析构函数“销毁”了返回值std::string。所以依靠这是非常危险的,因为无害的变化会导致它“摔倒”。