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

No final do artigo aqui: http://www.learncpp.com/cpp-tutorial/45-enumerated-types/ , ele menciona o seguinte:

Finalmente, como acontece com as variables ​​constantes, os tipos enumerados aparecem no depurador, tornando-os mais úteis do que os valores #definidos nesse aspecto .

Como a frase em negrito acima é alcançada?

Obrigado.

Considere este código,

#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; } 

Obviamente, cada multiplicação resulta em erro de compilation, mas veja como o GCC gera as mensagens para cada erro de multiplicação:

prog.cpp: 19: erro: nenhuma correspondência para ‘operator *’ em ‘eWidth * s’
prog.cpp: 20: erro: nenhuma correspondência para ‘operator *’ em ‘300 * s’
prog.cpp: 21: erro: nenhuma correspondência para ‘operator *’ em ‘Width * s’

Na mensagem de erro, você não vê a macro WIDTH que você #defined , certo? Isso ocorre porque no momento em que o GCC faz qualquer tentativa de compilar a linha corresponde ao segundo erro, ele não vê WIDTH , tudo o que ele vê é apenas 300, como antes o GCC compila a linha, o pré-processador substituiu WIDTH por 300. Por outro Por outro lado, não existe tal coisa acontece com enum eWidth e const Width .

Veja o erro você mesmo aqui: http://www.ideone.com/naZ3P


Além disso, leia o Item 2 : Prefer consts, enums, and inlines to #defines from Effective C ++ por Scott Meyers.

enum é constante de tempo de compilation com informações de debugging sem alocação de armazenamento.

const é alocado com um armazenamento, dependendo se é otimizado pelo compilador com propagação constante.

#define não tem alocação de armazenamento.

#define valores são substituídos pelo pré-processador com o valor que eles são declarados como, portanto, no depurador, ele só vê o valor, não o #defined name, por exemplo, se você tiver #define NUMBER_OF_CATS 10, no debugger você veja apenas 10 (já que o pré-processador substituiu cada instância de NUMBER_OF_CATS em seu código por 10.

Um tipo enumerado é um tipo em si mesmo e os valores são instâncias constantes desse tipo e, portanto, o pré-processador o deixa sozinho e você verá a descrição simbólica do valor no depurador.

O compilador armazena informações enum no binário quando o programa é compilado com certas opções.

Quando uma variável é do tipo enum, um depurador pode mostrar o nome do enum. Isso é melhor mostrado com um exemplo:

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

Se você compilar com o gcc -g você pode tentar o seguinte no 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 você usou um define, você não teria um tipo apropriado para dar e , e teria que usar um inteiro. Nesse caso, o compilador imprimiria 1 vez de ONE_E .

O sinalizador -g pede ao gdb para adicionar informações de debugging ao binário. Você pode até ver que está lá, emitindo:

 xxd test | grep ONE_E 

Eu não acho que isso funcionará em todas as arquiteturas, no entanto.

Pelo menos para o Visual Studio 2008 que tenho atualmente em mãos, esta frase está correta. Se você tem

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

e você definir um breakpont no main , você pode passar o mouse sobre “MyX” e ver que ele é avaliado como 3. Você não vê nada útil se você passar o mouse sobre X.

Mas isso não é uma propriedade de linguagem, mas sim um comportamento IDE. As próximas versões podem ser diferentes, assim como outras IDEs. Então, basta verificar para o seu IDE para ver se esta frase se aplica no seu caso.

Estou respondendo tarde demais, mas sinto que posso acrescentar algo – enum vs. const vs. #define

enum

  1. Não requer a definição de valores (se você quer apenas ter valores sequenciais 0, 1, 2 ..) enquanto que no caso de #defines você precisa manualmente gerenciar valores que podem causar erro humano em algum momento
  2. Funciona da mesma forma que durante a debugging on-line, o valor do enum pode ser observado na janela de exibição
  3. Você pode ter uma variável do tipo enum à qual você pode atribuir um enum

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

    int main (void) {número de números = CASE_TRUE; }

const

  1. É armazenado constantemente na área de memory somente de leitura, mas pode ser acessado usando o endereço que não é possível em caso de #define
    1. Você tem o tipo de check na sua mão se você usar const ao invés de #define
  2. define são diretiva de pré-processamento, mas const é tempo de compilation, por exemplo

    const char * name = “vikas”;

Você pode acessar o nome e usar seu endereço base para ler o tal como vikas [3] para ler ‘a’ etc.

#defines – são diretivas de pré-processador idiotas que substituem textualmente

Verifique o seguinte artigo, bom resumo http://www.queryhome.com/26340/define-vs-enum-vs-constant