2015-12-15 27 views
15

Una dichiarazione spesso usato come (void)x; permette di sopprimere gli avvertimenti circa variabile inutilizzata x. Ma se provo compilando il seguente, ho alcuni risultati che non capisco:Cosa colata a `void` davvero fare?

int main() 
{ 
    int x; 
    (short)x; 
    (void)x; 
    (int)x; 
} 

compilazione questo con g ++, ottengo le seguenti avvertenze:

$ g++ test.cpp -Wall -Wextra -o test 
test.cpp: In function ‘int main()’: 
test.cpp:4:13: warning: statement has no effect [-Wunused-value] 
    (short)x; 
      ^
test.cpp:6:11: warning: statement has no effect [-Wunused-value] 
    (int)x; 
     ^

Quindi concludo che la fusione a void è molto diverso da colata di qualsiasi altro tipo, tramite il tipo di destinazione uguale decltype(x) o qualcosa di diverso. La mia ipotesi a possibili spiegazioni è:

  • è solo una convenzione che (void)x; ma non gli altri calchi saranno sopprimere avvertimenti. Tutte le dichiarazioni ugualmente non hanno alcun effetto.
  • Questa differenza è in qualche modo legato al fatto che void x; non è una dichiarazione valida fino ad esaurimento short x; è.

Quale di questi, se c'è ne è più corretto? Se nessuno, come può essere spiegata la differenza negli avvisi del compilatore?

+2

E 'solo una convenzione tra i compilatori che questo cast sopprime avvertimenti. Lo standard C++ non menziona gli avvertimenti per "la dichiarazione non ha alcun effetto". –

risposta

20

La trasmissione a vuoto viene utilizzata per sopprimere gli avvisi del compilatore. Il Standard dice in §5.2.9/4 dice,

Qualsiasi espressione può essere convertito esplicitamente di tipo “cv vuoto.” Il valore espressione viene scartato.

8

Questa dichiarazione:

(void)x; 

Says "Ignora il valore di x." Non esiste un tipo come void - è l'assenza di un tipo. Quindi è molto diverso da questo:

(int)x; 

Che dice "Tratta x come se fosse un numero intero". Quando il numero intero risultante viene ignorato, viene visualizzato un avviso (se abilitato).

Quando si ignora qualcosa che non è nulla, non è considerato un problema da GCC - e con una buona ragione, dal momento che la trasmissione a vuoto è un modo idiomatico di ignorare una variabile esplicitamente in C e C++.

+0

Non ci ho mai pensato, ma sono un po 'confuso, pensi che potresti dare un esempio per chiarire il concetto di trasmettere una variabile a un 'vuoto? – Sacert

+4

Sono abbastanza sicuro che ci sia "un tipo come' void' ". Vedi [basic.types]. –

+0

@Sacert: '(void) x' sta trasmettendo una variabile a void. L'hai detto tu stesso. Ma una volta che lo hai fatto, non puoi fare nulla di più, perché l'espressione di vuoto non ha valore. –

4

Lo standard non richiede la generazione di un avviso ("diagnostico" in standard) per le variabili locali non utilizzate oi parametri di funzione. Allo stesso modo, non mandato come un tale avvertimento potrebbe essere soppresso. La trasmissione di un'espressione variabile a void per sopprimere questo avviso è diventata un idioma nella comunità C e successiva in C++, poiché il risultato non può essere utilizzato in alcun modo (ad eccezione di (int)x), quindi è improbabile che manchi il codice corrispondente. Ad esempio:

(int)x; // maybe you meant f((int)x); 
(void)x; // cannot have intended f((void)x); 
(void)x; // but remote possibility: f((void*)x); 

Personalmente, trovo questa convenzione troppo oscuro ancora, ed è per questo io preferisco usare un modello di funzione:

template<typename T> 
inline void ignore(const T&) {} // e.g. ignore(x); 

Il modo idiomatico di ignorare i parametri di funzione è, tuttavia, di omettere il loro nome (come visto sopra).Un uso frequente che ho per questa funzione è quando ho bisogno di essere in grado di nominare un parametro di funzione in un codice condizionato compilato come uno assert. Trovo ad es. la segue più leggibile che l'uso di #ifdef NDEBUG:

void rate(bool fantastic) 
{ 
    assert(fantastic); 
    ignore(fantastic); 
} 
+1

Dal C++ 17 puoi usare l'attributo '[[forse_unused]]' invece di tutti questi modi "creativi" per ignorare un parametro. – Ruslan