22

In another answer è stato affermato che prima di C++ 11, dove i è un int, quindi utilizzare l'espressione:Does * & ++ causo un comportamento non definito in C++ 03?

*&++i 

causato comportamento indefinito. È vero?

Sull'altra risposta c'era una piccola discussione nei commenti ma non sembra convincente.

+1

In questa risposta l'esperto "Johannes Schaub - litb" commenta che pensa che sia una dichiarazione non vera. E non ottiene risposta. –

+2

@DrewDormann James Kanze è anche molto ben informato –

+2

'* & i' sarebbe perfettamente valido, e' ++ i' restituisce un riferimento a 'i' quindi non vedo il problema io stesso ... –

risposta

0

Penso che la domanda ha senso solo se abbiamo a che fare con l'espressione:

i = *&++i; 

La citazione rilevante nello standard C++ 03 sarebbe [expr]/4:

Tranne dove notato, l'ordine di valutazione degli operandi dei singoli operatori e sottoespressioni delle singole espressioni e l'ordine in cui si verificano gli effetti collaterali, non è specificato. Tra il precedente e il successivo punto di sequenza 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 ordine consentito delle sottoespressioni di un'espressione completa ; altrimenti il ​​comportamento non è definito.

i = ++i + 1; // the behavior is unspecified 

Possiamo solo confrontare il sequenziamento del i = *&++i vs i = ++i + 1 per determinare che la stessa regola fa sì che sia per essere specificato. Entrambi sono enunciati della forma:

i = f(++i); 

Per ogni funzione f, la lettura i sul lato sinistro e l'effetto collaterale della ++i sul lato destro non sono in sequenza relativa con ogni altro. Quindi, comportamento indefinito.

7

Non ha molto senso chiedersi se *&++i abbia di per sé UB. Il deferencing non accede necessariamente al valore memorizzato (precedente o nuovo) di i, come puoi vedere usando questa come un'espressione di inizializzazione per un riferimento. Solo se è coinvolta una conversione di rvalue (utilizzo in tale contesto) c'è qualche domanda da discutere. E poi, dato che possiamo usare il valore di ++i, possiamo usare il valore di *&++i con esattamente gli stessi avvertimenti di ++i.

La domanda originale riguardava essenzialmente lo i = ++i, che è lo stesso di i = *&++i. Si trattava di un comportamento non definito in C++ 03, a causa del fatto che i veniva modificato due volte tra punti di sequenza ed era ben definito in C++ 11, a causa degli effetti collaterali dell'operatore di assegnazione che veniva sequenziato dopo il calcolo dei valori della sinistra e i lati della mano destra.

È forse importante notare che i non-normative esempi in C++ 98 e standard C++ 03, non erano corretti, descrive alcuni casi di comportamento formalmente Definire il comportamento puramente specificato. Pertanto, l'intento non è stato del tutto chiaro, al contrario.Una buona regola empirica è semplicemente non affidarsi a casi oscuri della lingua, per evitarli: uno non dovrebbe necessariamente essere un avvocato linguistico per dare un senso al codice & hellip;

+0

AFAICS 'i = ++ i' era ben definito in C++ 03, come mostrato correttamente dal risposta accettata nella Q/A collegata. – Columbo

+1

@Columbo: se vuoi essere così gentile da riassumere o citare, tenterò di confutare il reclamo che hai visto. Non riesco a trovarlo, mi dispiace. Tuttavia, poiché questo è stato molto semplice in C++ 03, assolutamente non modificare mai due volte o più tra i punti di sequenza, può darsi che non sia necessario altro? C++ 03 §5/4 in [expr]: "Tra il precedente e il successivo punto di sequenza un oggetto scalare deve avere il suo valore memorizzato modificato al massimo una volta dalla valutazione di un'espressione." –

+0

Apparentemente ho frainteso la nozione di sequenza punta interamente. Ho pensato che i paragrafi citati da questa [risposta] (http://stackoverflow.com/a/17403467/3647361) sarebbero sufficienti per dimostrare la ben definita di quell'espressione. Ma da nessuna parte viene detto qualcosa sui punti della sequenza (ho pensato che la loro esistenza sia * implicita *, ma ciò sembra sbagliato col senno di poi). In realtà, sembra che mentre si verificano così raramente definiscono un sacco di codice concettualmente bello da invocare UB. Fortunatamente è stato corretto in C++ 11. – Columbo