0

从这个问题和答案 - cout << c++ << c; 的正确答案是什么?

我明白了

std::cout<<c++<<c;

被评估为:

std::operator<<(std::operator<<(std::cout, c++), c);

所以未定义的行为来自于可以首先评估两个参数中的任何一个的事实。到现在为止还挺好。

但是为什么std::operator <<?为什么不std::ostream::operator <<叫?如果是的话,它不会转化为

(ofstream::operator<<(c++)) << c;
              |
     returns ofstream&

这和方法链接有什么区别:

struct A
{
    A& foo();
    void goo();
};
//...
A a;
a.foo().goo();

?

4

1 回答 1

3

std::ostream提供operator<<作为重载的成员操作符,但其他头文件(例如<string>)提供自由操作符;所以<<是成员运算符还是自由函数取决于 RHS 类型。

但是,这两种方式都没有关系。让我们重命名<<foocoutas bar

foo(foo(bar, c++), c);
bar.foo(c++).foo(c);

在这两种情况下,行为都是未定义的,因为没有要求实现以foo任何特定顺序评估要调用的参数。重要的考虑是,根据附件 C,链式方法调用不构成多个完整表达式;如果编译器看到

foo.bar(<some-complex-expression>).baz(<another-complex-expression>);

可以自由地对 tobar和to 的参数应用 CSE 和重新排序baz;确实,对副作用的检查可能表明参数 tobaz是在那些 to 之前评估的bar

struct A { A &foo(int) { return *this; } };
#include <cstdio>
int main() { A().foo(printf("hello\n")).foo(printf("bye\n")); }

我的编译器(gcc 4.1.2)生成一个打印bye\nhello\n.

于 2012-06-29T12:47:43.263 回答