Вызывается функция с оператором cout внутри оператора cout

Я столкнулся с этим довольно расплывчатым поведением, когда возился с кодом, вот пример:

#include <iostream>

using namespace std;


int print(void);

int main(void)
{
    cout << "The Lucky " << print() << endl;     //This line
    return 0;
}

int print(void)
{
    cout << "No : ";
    return 3;
}

В моем коде оператор с комментарием //This line должен был вывести The Lucky No : 3, но вместо этого было напечатано No : The Lucky 3. Что вызывает такое поведение? Связано ли это со стандартом С++ или его поведение варьируется от одного компилятора к другому?


person caramel1995    schedule 22.07.2012    source источник
comment
Почему вы считаете, что ваше ожидание, а не фактический результат, является более логичным? Можете ли вы объяснить свои рассуждения?   -  person stakx - no longer contributing    schedule 23.07.2012
comment
Примечание: ваша функция print — хороший пример функции с побочными эффектами. Помимо вычисления возвращаемого значения, он также изменяет глобальное состояние программы. О таких функциях обычно труднее рассуждать. Как правило, стремитесь к функциям, которые либо вычисляют значение , либо изменяют состояние, но не то и другое одновременно.   -  person stakx - no longer contributing    schedule 23.07.2012


Ответы (3)


Порядок оценки аргументов функции не указан. Ваша строка выглядит так для компилятора:

operator<<(operator<<(operator<<(cout, "The Lucky "), print()), endl);

Основным вызовом в операторе является вызов с endl в качестве аргумента. Не указано, будет ли сначала оцениваться второй аргумент, endl, или большее подвыражение:

operator<<(operator<<(cout, "The Lucky "), print())

И, разбивая это, не указано, вызывается ли функция print() первой или подвыражение:

operator<<(cout, "The Lucky ")

Итак, чтобы ответить на ваш вопрос:

Что вызывает такое поведение? Связано ли это со стандартом С++ или его поведение варьируется от одного компилятора к другому?

Это может варьироваться от компилятора к компилятору.

person Benjamin Lindley    schedule 22.07.2012
comment
Это вполне возможно, и я мог бы начать видеть это;) - person atamanroman; 23.07.2012
comment
@atamanroman: В следующем выражении: operator<<(operator<<(cout, "The Lucky "), print()) Как вы думаете, что должно произойти первым, это: operator<<(cout, "The Lucky ") или это: print()? Обосновать ответ. - person Benjamin Lindley; 23.07.2012
comment
Я знаю, это не определено, и я это знаю. Таким образом, cout ‹‹ Lucky + print() будет правильно определен? Удалил мой ответ (+1). - person atamanroman; 23.07.2012
comment
@atamanroman: Просто для точности вы можете знать, что есть разница между неопределенным и неопределенным поведением. Грубо говоря, неопределенное поведение означает, что может случиться что угодно; неуказанное поведение означает, что то, что происходит, зависит от реализации (но реализации не обязаны документировать то, что они делают). - person Stuart Golodetz; 23.07.2012
comment
@atamanroman: поведение не неопределенное, оно не указано - есть разница. Компилятор может оценивать параметры в любом порядке (включая случайный порядок), который он считает лучшим, он не может вообще не оценивать параметр или взорвать ваш тостер. - person jmoreno; 23.07.2012
comment
@atamanroman: cout << "The lucky" + print() выведет No : lucky. - person molbdnilo; 23.07.2012
comment
@BenjaminLindley Не могли бы вы также объяснить, как статусы переводятся в «оператор‹‹(оператор‹‹(оператор‹‹(cout, The Lucky ), print()), endl); ' - person Dexters; 03.10.2013

Назовем operator << просто operator .

Теперь мы можем написать

cout << "The Lucky"

as

operator(cout, "The Lucky")

Результатом этой операции является cout, и он передается следующему <<, поэтому мы можем написать

operator(operator(cout, "The Lucky"), print() )

Это вызов функции с двумя параметрами, и стандарт ничего не говорит о порядке их оценки.

Так что с некоторыми компиляторами вы действительно можете получить

The Lucky No : 3
person Adam Trhon    schedule 22.07.2012

В моем компиляторе No: Lucky 3 является выходом... это означает, что его поведение варьируется от компилятора к компилятору.

person Azhar Sindhi    schedule 20.11.2015