C ++ – enum vs. const vs. #define

Alla fine dell’articolo qui: http://www.learncpp.com/cpp-tutorial/45-enumerated-types/ , si menziona quanto segue:

Infine, come per le variabili costanti, i tipi enumerati appaiono nel debugger, rendendoli più utili dei # valori definiti a questo proposito .

Come si ottiene la frase in grassetto qui sopra?

Grazie.

Considera questo codice,

#define WIDTH 300 enum econst { eWidth=300 }; const int Width=300; struct sample{}; int main() { sample s; int x = eWidth * s; //error 1 int y = WIDTH * s; //error 2 int z = Width * s; //error 3 return 0; } 

Ovviamente ogni moltiplicazione si traduce in errore di compilazione, ma vedi come GCC genera i messaggi per ogni errore di moltiplicazione:

prog.cpp: 19: errore: nessuna corrispondenza per “operatore *” in “eWidth * s”
prog.cpp: 20: errore: nessuna corrispondenza per ‘operator *’ in ‘300 * s’
prog.cpp: 21: errore: nessuna corrispondenza per “operatore *” in “Larghezza * s”

Nel messaggio di errore, non vedi la macro WIDTH che hai #defined , giusto? Questo perché quando GCC fa un tentativo di compilare la riga corrisponde al secondo errore, non vede WIDTH , tutto vede solo 300, come prima che GCC compili la riga, il preprocessore ha già sostituito WIDTH con 300. Sull’altro mano, non succede nulla di simile con enum eWidth e const Width .

Vedi l’errore da solo qui: http://www.ideone.com/naZ3P


Inoltre, leggi l’ Item 2 : Prefer consts, enums, and inlines to #defines from Effective C ++ di Scott Meyers.

enum è una costante di tempo di compilazione con informazioni di debug senza allocazione di memoria.

const è allocato con una memoria, a seconda che sia ottimizzato via dal compilatore con propagazione costante.

#define non ha allocazione di memoria.

#define valori #define sono sostituiti dal pre-processore con il valore dichiarato come, quindi nel debugger vede solo il valore, non il nome #defined, ad esempio se hai #define NUMBER_OF_CATS 10, nel debugger vedi solo 10 (dal momento che il pre-processore ha sostituito ogni istanza di NUMBER_OF_CATS nel tuo codice con 10.

Un tipo enumerato è un tipo in sé e i valori sono istanze costanti di questo tipo, quindi il pre-processore lascia da solo e vedrai la descrizione simbolica del valore nel debugger.

Il compilatore memorizza le informazioni enum nel file binario quando il programma è compilato con determinate opzioni.

Quando una variabile è di tipo enum, un debugger può mostrare il nome dell’enumerazione. Questo è meglio mostrato con un esempio:

 enum E { ONE_E = 1, }; int main(void) { enum E e = 1; return 0; } 

Se lo compili con gcc -g puoi provare quanto segue in gdb :

 Reading symbols from test...done. (gdb) b main Breakpoint 1 at 0x804839a: file test.c, line 8. (gdb) run Starting program: test Breakpoint 1, main () at test.c:7 7 enum E e = 1; (gdb) next 9 return 0; (gdb) print e $1 = ONE_E (gdb) 

Se hai usato un define, non avresti un tipo corretto per dare e , e dovresti usare un numero intero. In tal caso, il compilatore stamperebbe 1 invece di ONE_E .

Il flag -g chiede a gdb di aggiungere informazioni di debug al binario. Puoi persino vedere che è lì emettendo:

 xxd test | grep ONE_E 

Non penso che funzionerà in tutte le architetture, però.

Almeno per Visual Studio 2008 che attualmente ho a disposizione, questa frase è corretta. Se hai

 #define X 3 enum MyEnum { MyX = 3 }; int main(int argc, char* argv[]) { int i = X; int j = (int)MyX; return 0; } 

e imposti un breakpont in main , puoi passare il mouse su “MyX” e vedere che valuta 3. Non vedi nulla di utile se passi il mouse su X.

Ma questa non è una proprietà del linguaggio, ma piuttosto un comportamento IDE. Le prossime versioni potrebbero farlo in modo diverso, così come altri IDE. Quindi basta controllare per il tuo IDE per vedere se questa frase si applica nel tuo caso.

Sto rispondendo troppo tardi ma sento di poter aggiungere qualcosa – enum vs. const vs. #define

enum

  1. Non richiede l’aggiunta di valori (se vuoi solo avere valori sequenziali 0, 1, 2 ..) mentre in caso di #definisci devi manualmente gestire i valori che potrebbero causare errori umani qualche volta
  2. Funziona come variabile durante il debug online, il valore di enum può essere visto nella finestra di controllo
  3. Puoi avere una variabile di tipo enum a cui puoi assegnare un enum

    numeri typedef enum {DFAULT, CASE_TRUE, CASE_OTHER,};

    int main (void) {numero numeri = CASE_TRUE; }

const

  1. È costante memorizzato in area di sola lettura della memoria, ma è ansible accedere utilizzando un indirizzo che non è ansible in caso di #define
    1. Hai un controllo di tipo nella tua mano se usi const anziché #define
  2. definisce la direttiva di pre-elaborazione ma const è ad esempio il tempo di compilazione

    const char * name = “vikas”;

È ansible accedere al nome e utilizzare il suo indirizzo di base per leggere i tipi come vikas [3] per leggere ‘a’ ecc.

#definiti : sono le direttive stupide del preprocessore che sostituiscono il testo

Controlla il seguente articolo, bel riassunto http://www.queryhome.com/26340/define-vs-enum-vs-constant