Jedną z nieprzyjemnych rzeczy na temat operatorów przekierowań <<
jest to, że intuicyjnie przekazują one indea "obliczeniowych obliczeń", których rzeczywiście nie ma.
Kiedy piszesz
std::cout << f() << g() << std::endl;
wyjście pokaże pierwszy wynik f()
a następnie wynik g()
, ale rzeczywiste wywołanie g()
może się zdarzyć przed wywołaniem f()
.
Jest nawet gorzej niż to ... nie jest tak, że sekwencja nie jest przewidywalna, ale że sama koncepcja sekwencji jest nieprawidłowa. W
std::cout << f(g()) << h(i()) << std::endl;
to na przykład prawne, że pierwsza funkcja nazywany jest g()
, a następnie i()
, a następnie h()
i wreszcie przez f()
. Nie ma nawet gwarancji, że zamówienie będzie takie samo dla wszystkich wywołań (nie dlatego, że twórcy kompilatorów lubią się z ciebie śmiać, ale dlatego, że kod może być wstawiony i kompilator może zdecydować o innej kolejności, jeśli funkcja zawierająca jest inkrementowana w innym kontekście).
Jedyne operatory C++, które gwarantują sekwencję w celu oceny są:
&&
: najpierw ocenia lewa strona i tylko wtedy, gdy wynik jest „true” ocenia prawej stronie
||
: najpierw ocenia lewej strony i tylko wtedy, gdy wynik jest „false” ocenia prawej stronie
?:
: ocenia pierwszy warunek, a potem dopiero drugi lub trzeci operand
,
: operator przecinka ... ocenia lewą stronę, odrzuca wartość, a następnie ocenia i zwraca prawą stronę. UWAGA: przecinki między parametrami funkcji NIE są operacjami przecinkowymi i nie jest narzucana kolejność oceny.
Ponadto ten guarate jest ważny tylko dla predefiniowanych operatorów. Jeśli przeładujesz &&
, ||
lub ,
w swojej klasie, są to zwykli operatorzy bez żadnych specjalnych ograniczeń dotyczących kolejności oceniania.
Dowolny inny operator nie nakłada żadnych ograniczeń na zlecenie oceny, a dotyczy to również użycia w rodzaju sztuczek, które można tak myśleć.
Prawdopodobnie to pytanie powinno ci to wyjaśnić: Jakie są różnice między zmienną wskaźnika a zmienną referencyjną w C++? (http://stackoverflow.com/questions/57483/what-are-the-differences-between-pointer-variable-and-reference-variable-in-c) – yasouser
To jest podobne (do http://stackoverflow.com/questions/18426473/pre-increment-not-working-as-i-expected/18426505 # 18426505). Brakuje punktu sekwencji. –