Tecnicamente, nel complesso questo è un comportamento indefinito .
Ma ci sono due aspetti importanti nella risposta.
La dichiarazione in codice:
std::cout << a++ << a;
è valutato come:
std::operator<<(std::operator<<(std::cout, a++), a);
Lo standard non definisce l'ordine di valutazione degli argomenti di una funzione.
Quindi O:
std::operator<<(std::cout, a++)
viene valutato prima o
a
viene valutato prima o
- potrebbe essere qualsiasi ordine definito dall'implementazione.
Questo ordine non è specificato [Rif 1] secondo lo standard.
[Rif 1] C ++ 03 5.2.2 Chiamata di funzione,
paragrafo 8
L'ordine di valutazione degli argomenti non è specificato . Tutti gli effetti collaterali delle valutazioni delle espressioni degli argomenti hanno effetto prima che la funzione venga inserita. L'ordine di valutazione dell'espressione postfissa e l'elenco delle espressioni degli argomenti non è specificato.
Inoltre, non vi è alcun punto di sequenza tra la valutazione degli argomenti di una funzione, ma esiste un punto di sequenza solo dopo la valutazione di tutti gli argomenti [Rif 2] .
[Rif 2] C ++ 03 1.9 Esecuzione del programma [intro.execution]:
Par. 17:
Quando si chiama una funzione (indipendentemente dal fatto che la funzione sia inline o meno), c'è un punto di sequenza dopo la valutazione di tutti gli argomenti della funzione (se presenti) che ha luogo prima dell'esecuzione di qualsiasi espressione o istruzione nel corpo della funzione.
Si noti che, qui c
si accede al valore di più di una volta senza un punto di sequenza intermedio, a questo proposito lo standard dice:
[Rif 3] C ++ 03 5 Espressioni [expr]:
Par. 4:
....
Tra il punto della sequenza precedente e quello successivo un oggetto scalare deve avere il suo valore memorizzato modificato al massimo una volta dalla valutazione di un'espressione. Inoltre, si accede al valore precedente solo per determinare il valore da memorizzare . I requisiti del presente paragrafo devono essere soddisfatti per ogni ordinamento ammissibile delle sottoespressioni di un'espressione completa; altrimenti il comportamento è indefinito .
Il codice viene modificato c
più di una volta senza intervenire sul punto della sequenza e non è possibile accedervi per determinare il valore dell'oggetto memorizzato. Questa è una chiara violazione della clausola di cui sopra e quindi il risultato come richiesto dallo standard è un comportamento indefinito [Rif 3] .