19

Recentemente ho attraversò di corsa la seguente situazione:Valutazione ordine degli argomenti di funzione e gli argomenti di default

#include <iostream> 

int *p = 0; 

int f() { 
    p = new int(10); 
    return 0; 
} 

void g(int x, int *y = p) { 
    std::cout << y << std::endl; 
} 

int main() { 
    g(f()); 
} 

Questo è abbastanza sottile, dal momento che di solito non si aspettano gli argomenti di default di cambiare durante la loro valutazione per la chiamata di funzione . Ho dovuto dare un'occhiata all'assembly per individuare questo errore.

Ora la mia domanda è: È questo comportamento davvero non definito, dal momento che non ci sono garanzie che regolano l'ordine di valutazione degli argomenti delle funzioni?

risposta

15

L'ordine di valutazione (vale a dire la determinazione del valore) degli argomenti di funzione non è specificato. Il compilatore è libero di eseguirli in qualsiasi ordine e anche mescolati se non ci sono altri fattori che lo impediscono.

La valutazione degli argomenti predefiniti avviene nel contesto del chiamante, non del chiamato. Quindi la chiamata a f() è necessaria per un argomento e la lettura della variabile globale p per l'altro. L'ordine in cui ciò avviene non è specificato, quindi il globale potrebbe essere letto prima o dopo la chiamata a f().

+0

"La valutazione degli argomenti predefiniti avviene nel contesto del chiamante" Hai un riferimento nello standard C++ corrente per questo reclamo? – phlipsy

+1

C'è una nota non normativa in 1.9p11 che la dice esplicitamente. Oltre a questo, penso che sia solo implicito dalla mancanza di distinzione da altri argomenti. –

+2

@phlipsy si veda [dcl.fct.default]/9 "Gli argomenti predefiniti vengono valutati ogni volta che viene chiamata la funzione L'ordine di valutazione degli argomenti della funzione non è specificato.", Penso che ciò implichi chiaramente che 'g (f()) 'è uguale a' g (f(), p) ' –

13

Se ho ben capito, la chiamata

g(f()); 

è equivalente a

g(f(), p); 

a causa della dichiarazione di

void g(int x, int *y = p); 

e gli argomenti alla funzione g, f() e p , può essere valutato in qualsiasi ordine, in modo da poter ottenere 01 Chiamato con y assegnato a zero (se p viene valutato per primo, quindi restituisce il suo valore iniziale) o il puntatore dell'array appena assegnato (se f() viene valutato per primo e assegna un nuovo valore a p come effetto collaterale).

Problemi correlati