2013-09-05 10 views
6

Dopo essere stato morso da fare qualcosa di simile:Evitare/guardia di sé l'inizializzazione del C++ membri

struct Person { 

    std::string first_name; 
    std::string last_name; 
    Person(const std::string &first_name_, const std::string &last_name_) : 
    first_name(first_name_), 
    last_name(last_name) 
    {} 
}; 

Qualora l'inizializzazione last_name(last_name) dovrebbe ovviamente essere last_name(last_name_) sono là tutto il senso che posso fare gcc mettere in guardia circa un errore del genere (c'è mai qualche caso d'uso di inizializzare un utente che usa se stesso?)

O qualsiasi suggerimento su una migliore convenzione di denominazione nei casi in cui gli argomenti del costruttore sono simili ai campi.

+1

La convenzione più diffusa è far precedere membri con la lettera "m" (utente) o "f" (campo). Come "mLastName" o "m_last_name". Questo è utile non solo a causa di questo problema specifico, ma anche perché immediatamente sai che qualcosa è una variabile membro se ha il prefisso. È anche meno probabile che si sbagli; il suffisso "_" consente comunque il completamento automatico per suggerire sia l'argomento che il membro. Con un prefisso questo non succede spesso. –

+0

@NikosC. quando ho iniziato a programmare l'avrei usato dappertutto, insieme ad altri tipi di notazione ungherese come m_pfnFoo per i puntatori di funzioni, ecc. Poi, come esperimento, ho deciso di liberarmene e non l'ho mai perso. Ho l'impressione che quando le tue classi sono create con cura non offre alcun vantaggio. – stijn

+0

@stijn Trovo molto utile specialmente quando si legge il codice di altre persone. Rende un po 'più facile capirlo. Mi fa usare meno spesso la funzionalità di ricerca del mio IDE, che è una buona cosa :) –

risposta

9

Evito il problema utilizzando lo stesso nome per gli argomenti come i membri che inizializzano. Le regole di ricerca specificano che il nome si riferisce all'argomento, se utilizzato in un inizializzatore del membro.

C'è spazio per errori sottili se il costruttore è troppo complicato; ma nessun problema se stai semplicemente inizializzando i membri nella lista di inizializzazione.

In caso contrario, GCC darà un avvertimento sull'utilizzo di un valore di Non inizializzato con le impostazioni di allarme sensibili come -Wall (o forse -Wextra), o più specificamente -Wuninitialized. Penso che potrebbe esserci anche un -Winit-self o simile, se vuoi essere ancora più specifico.

+3

+1. È meglio, poiché evita anche di pensare due nomi per la stessa entità. Le soluzioni semplici di solito sono le migliori. – Nawaz

+1

@JonasWielicki: abbastanza giusto. Io uso sempre '-Wall -Wextra', e non incontro mai questo problema in ogni caso, quindi non saprei esattamente di cosa avresti bisogno. –

+0

Ho appena testato, '' -Wall'' * sembra * funzionare ora, questo potrebbe essere cambiato con gcc 4.8. –

7

Sì; -Wuninitialized e -Winit-self:

$ g++ -Wuninitialized -Winit-self -c init.cpp 
init.cpp: In constructor 'Person::Person(const string&, const string&)': 
init.cpp:7:3: warning: 'Person::last_name' is initialized with itself [-Wuninitialized] 
+0

Ho ridacchiato a "opzione non riconosciuta" :) – jrok

+1

@jrok Hehe - Non posso spendere per la vita di me. – trojanfoe

+0

Quando uso g ++ (oggetto di compilazione diretta) l'errore sopra non lo fa. Qualche ragione specifica? Anche con -Wall –