2012-06-29 1 views
0

С этого вопроса & ответы - What is the correct answer for 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(); 

?

+2

Нет большой разницы. Если вы делаете 'a.foo (C++). Goo (c)' у вас опять такая же проблема. –

ответ

3

std::ostream обеспечивает operator<< как перегруженные операторы-члены, но другие заголовки (например, <string>) предоставляют бесплатные операторы; так ли << является оператором-членом или бесплатная функция зависит от типа RHS.

Однако это не имеет значения в любом случае. Давайте переименовать << в foo и cout в bar:

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

В обоих случаях поведение не определено, поскольку не существует никаких требований об осуществлении оценить аргументы либо вызвать к foo в любом порядке. Важное соображение состоит в том, что в Приложении C вызов с цепным методом не составляет более одного полного выражения; если компилятор видит

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

это свободно применять ЭПС и переназначения на аргументы bar и baz; действительно, рассмотрение побочных эффектов может показать, что аргументы baz оцениваются до этих значений до 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.

+1

Первое предложение неверно, оно зависит от [типа аргумента] (http://en.cppreference.com/w/cpp/io/basic_ostream/operator_ltlt) –

+0

@JesseGood спасибо, исправлено. – ecatmur