Parlare nel contesto dello standard C++ 11 (che non ha più un concetto di punti di sequenza, come sai) voglio capire come sono definiti due esempi più semplici.Ordine di valutazione e comportamento non definito
int i = 0;
i = i++; // #0
i = ++i; // #1
ci sono due temi su SO che spiegano questi esempi nel contesto C++ 11. Here è stato detto che #0
invoca UB e #1
è ben definito. Here è stato detto che entrambi gli esempi non sono definiti. Questa ambiguità mi confonde molto. Ho letto questo ben strutturato reference tre volte ma l'argomento sembra essere troppo complicato per me.
.
Analizziamo l'esempio #0
: i = i++;
.
citazioni corrispondenti sono:
Il valore di calcolo incorporato postincremento e postdecrement operatori viene sequenziato prima del suo effetto collaterale.
L'effetto collaterale (modifica dell'argomento sinistra) del built-in operatore di assegnazione e di tutti gli operatori di assegnazione composti incorporati viene sequenza dopo il calcolo del valore (ma non gli effetti collaterali) di sia a sinistra e giuste argomentazioni, e viene sequenziato prima che il valore calcolo dell'espressione di assegnazione (cioè, prima di tornare il riferimento all'oggetto modificato)
Se un effetto collaterale su un oggetto scalare è non in sequenza rispetto ad un altro lato effetto sullo stesso oggetto scalare, il comportamento non è definito.
Come ho capito, l'effetto collaterale di l'operatore di assegnazione non viene sequenziato con effetti collaterali di esso è rimasto e gli argomenti giusti. Pertanto, l'effetto collaterale dell'operatore di assegnazione non viene sequenziato con gli effetti collaterali di i++
. Quindi #0
invoca un UB.
.
Analizziamo l'esempio #1
: i = ++i;
.
citazioni corrispondenti sono:
L'effetto collaterale dei incorporati preincremento e predecremento operatori viene sequenza prima della computazione valore (regola implicita causa a definizione come assegnazione composta)
L'effetto collaterale (modifica dell'argomento a sinistra) dell'operatore di assegnazione incorporato e di tutti gli operatori di assegnazione composti incorporati è sequenziati dopo il calcolo del valore (ma non gli effetti collaterali) di argomenti destro e sinistro, e viene sequenziato prima che il valore calcolo dell'espressione di assegnazione (cioè, prima di tornare il riferimento all'oggetto modificato)
Se un effetto collaterale su un oggetto scalare è ingiustificato rispetto ad un altro effetto collaterale sullo stesso oggetto scalare, il comportamento non è definito.
non riesco a vedere, come questo esempio è diverso dal #0
. Questo sembra essere un UB per me per lo stesso motivo di #0
. L'effetto collaterale dell'assegnazione non è sequenziato con l'effetto collaterale di ++i
. Sembra essere un UB. L'argomento sopra suggerito dice che è ben definito. Perché?
.
Domanda: come posso applicare le regole citate per determinare la UB degli esempi. Una spiegazione il più semplice possibile sarebbe molto apprezzata. Grazie!
Avrei una conversazione piuttosto franca con il programmatore se ho visto questo nel codice di produzione. Sì, è una curvatura intellettuale, ma non riesco a vedere molto merito nel pensare troppo a questo. Detto questo, +1 per la domanda ben scritta e leggerò in dettaglio la risposta accettata. – Bathsheba
@Bathsheba Concordo sul fatto che quegli esempi di codice non dovrebbero probabilmente mai essere in un codice reale, ma penso che la comprensione dello standard aiuterà a determinare l'UB in altri esempi. – Kolyunya
Ti ho upvoted sulla qualità della domanda e, come te, attendo una risposta di qualità simile. – Bathsheba