cout <<ordine di chiamata alle funzioni stampa?
Domanda
il seguente codice:
myQueue.enqueue('a');
myQueue.enqueue('b');
cout << myQueue.dequeue() << myQueue.dequeue();
stampa "ba" sulla console
Mentre:
myQueue.enqueue('a');
myQueue.enqueue('b');
cout << myQueue.dequeue();
cout << myQueue.dequeue();
stampa "ab" perché?
Sembra che cout stia chiamando prima la funzione più esterna (la più vicina alla ;) e si stia facendo strada, è così che si comporta?
Soluzione
Non esiste un punto di sequenza con il <<
operatore in modo che il compilatore sia libero di valutarli dequeue
prima la funzione.Ciò che è garantito è che il risultato del secondo dequeue
call (nell'ordine in cui appare nell'espressione e non necessariamente nell'ordine in cui viene valutata) è <<
'ed al risultato di <<
'il primo (se capisci cosa sto dicendo).
Quindi il compilatore è libero di tradurre il tuo codice in qualcosa di simile a uno di questi (pseudo intermedio C++).Questo non vuole essere un elenco esaustivo.
auto tmp2 = myQueue.dequeue();
auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;
O
auto tmp1 = myQueue.dequeue();
auto tmp2 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
tmp3 << tmp2;
O
auto tmp1 = myQueue.dequeue();
std::ostream& tmp3 = cout << tmp1;
auto tmp2 = myQueue.dequeue();
tmp3 << tmp2;
Ecco a cosa corrispondono i temporanei nell'espressione originale.
cout << myQueue.dequeue() << myQueue.dequeue();
| | | | |
| |____ tmp1 _____| |_____ tmp2 ____|
| |
|________ tmp3 _________|
Altri suggerimenti
La chiamata dal tuo esempio:
cout << myQueue.dequeue() << myQueue.dequeue();
si traduce nella seguente espressione con due chiamate di operator<<
funzione:
operator<<( operator<<( cout, myQueue.dequeue() ), myQueue.dequeue() );
-------------------- 1
---------2
L'ordine di valutazione di cout
, myQueue.dequeue()
non è specificato.Tuttavia, l'ordine di operator<<
le chiamate alle funzioni sono ben specificate, come contrassegnato con 1
E 2
Dal C++17 il comportamento di questo codice è cambiato;l'operando sinistro di <<
viene sequenziato prima dell'operando destro di <<
, anche quando si tratta di un operatore sovraccarico.L'output deve ora essere ab
.
Per ulteriori letture vedere: Quali sono le garanzie dell'ordine di valutazione introdotte da C++17?.