Ordine di valutazione nei parametri della funzione C ++


90

Se abbiamo tre funzioni (foo, bar e baz) che sono composte in questo modo ...

foo(bar(), baz())

C'è qualche garanzia dallo standard C ++ che la barra verrà valutata prima di baz?

Risposte:


102

No, non esiste tale garanzia. Non è specificato secondo lo standard C ++.

Bjarne Stroustrup lo dice anche esplicitamente in "The C ++ Programming Language" 3a edizione sezione 6.2.2, con alcune ragioni:

È possibile generare codice migliore in assenza di restrizioni sull'ordine di valutazione dell'espressione

Sebbene tecnicamente questo si riferisca a una parte precedente della stessa sezione che dice che anche l'ordine di valutazione delle parti di un'espressione non è specificato, cioè

int x = f(2) + g(3);   // unspecified whether f() or g() is called first

Posso accettare questa risposta in 8 minuti ... immagino di restare in giro per un po '!
Clark Gaebel

4
Sì, ma il codice migliore potrebbe essere SCRITTO (= più pulito) se l'ordine di valutazione dell'espressione fosse RIGOROSO, che è generalmente molto più importante della generazione del codice. Guarda questo esempio: stackoverflow.com/questions/43612592/… Quindi ecco, Stroustrup.
Bill Kotsias

1
Se l'ordinazione è importante, sei libero di eseguire la sequenza da solo. Fare altrimenti comporterebbe sempre un costo per qualcosa che non sempre (raramente?) Conta. Penso che la politica di non pagare ciò che non usi sia l'unica cosa su cui la maggior parte dei programmatori C ++ è d'accordo.
tweej

3
Non dovrebbe essere "comportamento non specificato" invece di "non definito"?
GoodDeeds

1
@ChrisDodd votare una risposta accettata a causa dell'uso della parola "indefinito" rispetto a "non specificato" mi sembra pedanteria maliziosa ... non ho detto che questo è "comportamento indefinito", e altrimenti "non definito" e "non specificato" sembrano sinonimo? In ogni caso, proporre una modifica alla risposta sarebbe stato un modo più produttivo per discuterne
Eli Bendersky,

21

Da [5.2.2] Chiamata di funzione,

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.

Pertanto, non vi è alcuna garanzia che bar()verrà eseguito prima baz(), solo quello bar()e baz()verrà chiamato prima foo.

Nota anche da [5] Expressions che:

tranne dove indicato [ad esempio regole speciali per &&e ||], l'ordine di valutazione degli operandi dei singoli operatori e delle sottoespressioni delle singole espressioni e l'ordine in cui si verificano gli effetti collaterali non è specificato.

quindi anche se stavi chiedendo se bar()verrà eseguito prima baz()in foo(bar() + baz()), l'ordine non è ancora specificato.


4
Un esempio di una "nota speciale" da [5.14] Operatore AND logico: "Diversamente &, &&garantisce la valutazione da sinistra a destra: il secondo operando non viene valutato se il primo operando è false."
Daniel Trebbien

20

Non esiste un ordine specificato per bar () e baz () - l'unica cosa che lo Standard dice è che saranno entrambi valutati prima che venga chiamato foo (). Dallo standard C ++, sezione 5.2.2 / 8:

L'ordine di valutazione degli argomenti non è specificato.


4
Il fatto che siano valutati prima di foo () è almeno un po 'rassicurante.
Bill Kotsias

1
@BillKotsias Lo standard dice anche che le chiamate di funzione non possono sovrapporsi (cioè un'implementazione non può eseguire la riga 1 di bar, quindi la riga 1 di baz, quindi la riga 2 di bar, ecc.), Il che è anche bello. :-)
melpomene


3

In C ++ 11, il testo pertinente può essere trovato in 8.3.6 Argomenti predefiniti / 9 (Enfasi mia)

Gli argomenti predefiniti vengono valutati ogni volta che viene chiamata la funzione. L'ordine di valutazione degli argomenti della funzione non è specificato . Di conseguenza, i parametri di una funzione non devono essere utilizzati in un argomento predefinito, anche se non vengono valutati.

La stessa verbosità è usata anche dallo standard C ++ 14 e si trova nella stessa sezione .


0

Come altri hanno già sottolineato, lo standard non fornisce alcuna guida sull'ordine di valutazione per questo particolare scenario. Questo ordine di valutazione viene quindi lasciato al compilatore e il compilatore potrebbe avere una garanzia.

È importante ricordare che lo standard C ++ è in realtà un linguaggio per istruire un compilatore sulla costruzione di codice assembly / macchina. Lo standard è solo una parte dell'equazione. Dove lo standard è ambiguo o è specificatamente definito dall'implementazione, dovresti rivolgerti al compilatore e capire come traduce le istruzioni C ++ in vero linguaggio macchina.

Quindi, se l'ordine di valutazione è un requisito, o almeno importante, e l'essere compatibili con i compilatori non è un requisito, cerca di capire come il tuo compilatore alla fine metterà insieme tutto questo, la tua risposta potrebbe essere lì. Nota che il compilatore potrebbe cambiare la sua metodologia in futuro

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.