Cosa succede quando chiamo una funzione senza assegnare il suo valore restituito a una variabile?

Diciamo che ho la seguente funzione:

int foo() { return 1234; } 

Qual è l’effetto di chiamare questa funzione senza assegnare il suo valore restituito a qualsiasi variabile:

 foo(); 

Inoltre, qual è l’effetto dell’utilizzo di un operatore senza assegnare il valore restituito a qualsiasi variabile:

 1 + 2 + 3; 

In C ++ un’espressione è un’istruzione valida; il valore calcolato viene semplicemente scartato.

Alcuni compilatori sono abbastanza intelligenti da avvertirti con un avviso se il codice sembra strano; per esempio avendo:

 foo(1,2,3); 

può avere senso (chiama la funzione che probabilmente ha effetti collaterali) ma come il codice

 x < 3; 

non è utile perché non ha effetti collaterali definiti e il valore viene scartato.

In g ++ ci sono anche alcune funzioni della libreria che, nonostante abbiano effetti collaterali, sono contrassegnate in modo specifico in modo che ignorare il valore restituito sollevi un avvertimento (come il fread ) perché è un segno di un bug in attesa di mordere.

Esistono anche casi molto comuni in cui l'ignorare il risultato di una funzione viene eseguito frequentemente (come printf ) e in cui le espressioni che restituiscono un valore vengono utilizzate solo per l'effetto collaterale (come std::cout << "Hello"; ).

Se si desidera applicare in fase di esecuzione che il risultato di una funzione non sia stato ignorato silenziosamente, è ansible che a volte sia ansible utilizzare un trucco:

 template struct must_check { T x; bool checked; must_chec(const T& x) : x(x), checked(false) {} operator T () { checked = true; return x; } ~must_check() { if (!checked) throw std::runtime_error("Result value has not been checked"); } }; 

Ora invece di scrivere

 int square(int x) { return x * x; } 

Scrivi e basta

 must_check square(int x) { return x * x; } 

Quindi codice come

 square(12); 

genererà un'eccezione in fase di esecuzione, mentre

 int result = square(12); 

funzionerà bene

Questo è ansible, ma non è comunque una buona idea, perché lanciare un'eccezione in un distruttore è un comportamento veramente brutto che spesso si risolve nel terminare un programma in modo anomalo (la ragione è che a volte i distruttori vengono chiamati automaticamente a causa di un'eccezione, lanciando un altro l'eccezione durante quella fase è una mossa letale).

L’operazione o la funzione saranno valutate e continueranno a funzionare. A seconda del compilatore, è ansible che venga visualizzato un avviso, altrimenti continuerà a essere eseguito senza problemi.

Non sei obbligato a fare nulla con il valore restituito da una funzione in C ++. Puoi chiamare la funzione e semplicemente ignorare il valore restituito. Anche l’operatore è una funzione, quindi puoi chiamarla, quindi l’espressione sarà valutata e ancora una volta – il risultato potrebbe essere solo dimenticato.

A un livello basso, quando una funzione restituisce un valore, questo valore viene copiato nel registro eax (su computer a 32 bit) o ​​rax (macchina a 64 bit), quindi la funzione chiamante utilizza il registro eax o rax per leggere i dati restituiti. In questo caso la funzione chiamante non legge i registri eax / rax.