объясните про c++

elenangel

что-то я туплю:
 
 
#include <iostream>
using namespace std;

string x = "0";

string g1
{
string result = x;
x = "1";
cout<<"g1"<<endl;
return "g1("+result+")";
}

string g2
{
string result = x;
x = "2";
cout<<"g2"<<endl;
return "g2("+result+")";
}
string g3
{
string result = x;
x = "3";
cout<<"g3"<<endl;
return "g3("+result+")";
}

int main(int,char**)
{
cout<<"'"<<g1<<"' '"<<g2<<"' '"<<g3<<"'"<<endl;
cout<<"Expected:\ng1\ng2\ng3\n'g1(0)' 'g2(1)' 'g3(2)'"<<endl;
return 0;
}

 
g3
g2
g1
'g1(2)' 'g2(3)' 'g3(0)'
Expected:
g1
g2
g3
'g1(0)' 'g2(1)' 'g3(2)'
  

я думал что первая строка в main напечатает то, что напечатано после 'Expected:'
иными словами, почему выражения для оператора << вычисляются в порядке обратном его ассоциированию и в обратном от появления их в тексте программы?

Maurog

я думал что первая строка в main напечатает то, что напечатано после Expected:
порядок вычисления аргументов функции не определен.
вы не видите здесь эту функцию?
вспомните сигнатуру функции<< и перепишите ваше выражение с << в терминах вызова этой функции
тогда должно стать все ясно

elenangel

порядок вычисления аргументов функции не определен.
функцию я вижу. а вот про "неопределён" это к одной функции относится? или к выражению?
там ведь

cout.operator<<("'").operator<<(g1.operator<<("' '").operator<<(g2.operator<<("' '").operator(g3.operator("'");

как бы я надеялся что аргументы для такой цепочки вызовов вычисляются в порядке вызовов.
это ведь не один вызов с кучей параметров, а последовательность.

Maurog

cout.operator<<
вот тут промашка :o

elenangel

да, я уже понял что на самом деле это
 
operator<<(operator<<(operator<<(operator<<(operator<<(operator<<(operator<<(cout,"'"g1"' '"g2"' '"g3"'").operator<<(endl);  

elenangel

опять же непонятно почему он не начинает вычислять параметры начиная с самого вложенного вызова

Maurog

опять же непонятно почему он не начинает вычислять параметры начиная с самого вложенного вызова
вот смотрим:
f(g h
вы в голове сначала g вызываете, а компиляторы легче сначала h вызвать (стандарт ему дал такую свободу)
в итоге, если всегда вычислять сначала правый аргумент, затем левый, то получим то, что напечатала ваша программа
если же вычислять сначала левый, затем правый аргумент, то будет ваш Expected

Maurog

я даже выскажу гипотезу, почему сначала правый аргумент вычисляется : из-за порядка передачи параметров в функцию
http://ru.wikipedia.org/wiki/%D0%A1%D0%BE%D0%B3%D0%BB%D0%B0%...
во многих соглашениях
Аргументы передаются через стек, справа налево

Devid

Короче вывод: так делать не надо.

elenangel

спасибо, вроде прояснилось.
Оставить комментарий
Имя или ник:
Комментарий: