2016-06-20 23 views
16
#include <vector> 

class Object 
{ 
}; 

int main() 
{ 
    Object myObject; 
    std::vector<int> myVector; 
} 

compilatore emette:Perché il compilatore non emette un avviso quando un oggetto std :: vector è dichiarato ma mai usato?

Nessun avvertimento per myVector. Perché? C'è un modo per abilitare questo?

+2

In C++, i costruttori e i distruttori possono contenere una logica non banale. Quindi, in generale, è indecidibile se una dichiarazione di variabili apparentemente inutilizzata possa essere effettivamente eliminata. – pyon

+1

Emette l'avviso quando si aggiunge un costruttore non banale del parametro zero a Object? – lorro

risposta

20

Se la dichiarazione (e quindi l'inizializzazione e, a un certo punto, destructung) di un oggetto arbitrario ha effetti collaterali visibili non può essere determinata in generale. Il costruttore può chiamare funzioni la cui definizione non è nota al compilatore o può dipendere dallo stato esterno o da qualsiasi altro aspetto che renda il problema indecidibile.

Nel primo caso, il costruttore è banale (nemmeno dichiarato), lo stesso per il distruttore. Siccome lo Object non ha membri, è chiaro e facilmente rilevabile che lo Object foo in effetti non fa nulla.

std::vector ha un costruttore non banale che può essere allocando memoria (stato esterno + funzione la cui definizione non può essere conosciuta (new ...)) con un distruttore non banale (anche stato esterno + funzione la cui definizione non può essere conosciuto (delete ...)). Ragionare sul fatto che sia sicuro rimuovere la dichiarazione (emettendo in tal modo un avvertimento che probabilmente dovresti) non è possibile in questo caso, quindi il compilatore deve lasciare la dichiarazione nel codice (e deve presumere che la dichiarazione sia lì per un ragionare).

Un primo esempio è std::lock_guard che viene utilizzato per bloccare un mutex quando è costruito e sbloccarlo automaticamente quando viene distrutto. Il mutex è quindi mantenuto finché l'oggetto è nel campo di applicazione; generalmente non si può accedere all'oggetto std::lock_guard, tuttavia è utile dichiararlo. Questo è il principio RAII al lavoro.

Emettere un avviso in questi casi sarebbe un fastidio, portando le persone a disattivare l'avviso, che a sua volta renderebbe l'avviso inutile. (Il compilatore può anche essere progettato in modo tale che emetta solo l'avviso se ha rimosso la dichiarazione durante l'ottimizzazione, che è anche il motivo per cui alcuni avvisi vengono visualizzati solo se determinate ottimizzazioni sono abilitate.)

6

Questa avvertenza è generato solo per tipi banali. Il compilatore non è in grado di scoprire se il costrutto chiamerà qualsiasi funzione esterna. Se aggiungi un costruttore alla tua classe Object, il compilatore emetterà anche un avviso. Gcc permette di taggare i tipi che dovrebbe generare questo avviso, è possibile farlo usando __attribute__((warn_unused)):

http://coliru.stacked-crooked.com/a/0130c8ef29c121a1

esempio:

class __attribute__((warn_unused)) Object 
{ 
    public: 
    Object(){} 
    void use() {} 
}; 

int main() 
{ 
    Object myObject; // will give : warning: unused variable 'myObject' [-Wunused-variable] 
    //myObject.use(); // uncomment to hide this warning 
} 

[modifica]

da gcc attributi pagina: https://gcc.gnu.org/onlinedocs/gcc/C_002b_002b-Attributes.html:

warn_unused Per i tipi C++ con distruttori non banali e/o distruttori è impossibile per il compilatore determinare se una variabile di questo tipo è veramente inutilizzata se non viene referenziata.Questo attributo di tipo informa il compilatore che le variabili di questo tipo devono essere avvisate se sembrano non essere utilizzate, proprio come le variabili dei tipi fondamentali . Questo attributo è appropriato per i tipi che solo rappresentano un valore, come std :: string; non è appropriato per i tipi che controllano una risorsa, come std :: lock_guard.

Questo attributo è accettato anche in C, ma non è necessario in quanto C non ha costruttori o distruttori.

+1

Quindi, dovrebbe libstdC++ contrassegnare la maggior parte dei suoi tipi con questo attributo? Dovrebbero invece avere un attributo no_warn_unused per il blocco e tipi simili e avvisare per impostazione predefinita? –

+2

@MarcGlisse sei corretto (voglio dire segnando il 99% di libstdC++), e c'è una discussione aperta su questo qui: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=55203. – marcinj

+1

Sono d'accordo con Marc, dovrebbe essere il comportamento predefinito. – Jovini

2

Così come le risposte sopra, controlla anche la documentazione del compilatore. Alcuni compilatori possono essere impostati in modo tale da non mostrare più volte lo stesso avviso. Se si commenta la dichiarazione di "myObject", è possibile ottenere lo stesso avviso per "myVector". Con "mObject" che produce prima questo avviso, non si ottiene un avviso per "myVector".

Il comportamento del compilatore in caso di avvisi è molto specifico del compilatore, quindi non dare per scontato che tutti i compilatori funzionino allo stesso modo. :)