Приоритет оператора для «<<» и «++» в VS2008 с оптимизацией - PullRequest
8 голосов
/ 12 августа 2010

Я застрял со странной проблемой VS2008 C ++, которая выглядит так, будто приоритет оператора не соблюдается.

У меня вопрос, что выводится:

int i = 0;  
std::cout << ((i != 0) ? "Not zero " : "zero ") << ++i << std::endl;  

Обычно++ имеет приоритет над <<, верно?Или << считается вызовом функции, что дает ему более высокий приоритет, чем ++?Каков на 100% правильный стандартный ответ на этот вопрос?

Чтобы проверить, я создал новый пустой проект (консольное приложение VS2008), вставил в этот код только этот код, и вот результаты:

Debug|Win32: “zero 1”  
Release|Win32: “zero 1”  
Debug|x64: “zero 1”  
Release|x64: “Not zero 1”

Кстати, следующий пример дает точно такие же результаты:

i = 0;  
printf("%s %d\n", ((i != 0) ? "Not zero" : "zero"), ++i);  

А также изменение типа оптимизации в выпуске не имеет никакого эффекта, но отключение оптимизации выводит «ноль 1», как и другие конфигурации.

1 Ответ

16 голосов
/ 12 августа 2010

Это не имеет ничего общего с приоритетом оператора.
Вы используете <<, что является синтаксическим сахаром для вызова функции: </p>

std::cout << ((i != 0) ? "Not zero " : "zero ") << ++i << std::endl; 

// Equivalent too:

operator<<(operator<<(operator<<(std::cout, ((i != 0) ? "Not zero " : "zero ")), ++i), std::endl);

Единственное правило здесь состоит в том, что параметр должен быть полностью оценен перед вызовом функции. Нет никаких ограничений относительно того, в каком порядке оцениваются параметры или даже если их оценка чередуется с вызовами (или даже частично оценивается).

Интерпретация 1:

1) ((i != 0) ? "Not zero " : "zero "))
2) ++i
3) operator<<(std::cout, (1));
4) operator<<((3), (2));
5) operator<<((4), std::endl);

Интерпретация 2:

1) ++i
2) ((i != 0) ? "Not zero " : "zero "))
3) operator<<(std::cout, (2));
4) operator<<((3), (1));
5) operator<<((4), std::endl);

Интерпретация 3:

1) ((i != 0) ? "Not zero " : "zero "))
2) operator<<(std::cout, (1));
3) ++i
4) operator<<((2), (3));
5) operator<<((4), std::endl);

Рассматривая толкование 1 как ссылку:
Правила, которые должны применяться:

 A) (1) happens before (3)
 B) (2) happens before (4)
 C) (3) happens before (4)
 D) (4) happens before (5)
...