C++ - enum vs. const vs. #define
At the end of the article here: http://www.learncpp.com/cpp-tutorial/45-enumerated-types/, it mentions the following:
Finally, as with constant variables, enumerated types show up in the debugger, making them more useful than #defined values in t开发者_C百科his regard.
How is the bold sentence above achieved?
Thanks.
Consider this code,
#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;
}
Obviously each multiplication results in compilation-error, but see how the GCC generates the messages for each multiplication error:
prog.cpp:19: error: no match for ‘operator*’ in ‘eWidth * s’
prog.cpp:20: error: no match for ‘operator*’ in ‘300 * s’
prog.cpp:21: error: no match for ‘operator*’ in ‘Width * s’
In the error message, you don't see the macro WIDTH
which you've #defined
, right? That is because by the time GCC makes any attempt to compile the line corresponds to second error, it doesn't see WIDTH
, all it sees only 300, as before GCC compiles the line, preprocessor has already replaced WIDTH
with 300. On the other hand, there is no any such thing happens with enum eWidth
and const Width
.
See the error yourself here : http://www.ideone.com/naZ3P
Also, read Item 2 : Prefer consts, enums, and inlines to #defines
from Effective C++ by Scott Meyers.
enum
is compile time constant with debug info with no storage allocation.
const
is allocated with a storage, depending on whether it is optimised away by the compiler with constant propagation.
#define
has no storage allocation.
#define
values are replaced by the pre-processor with the value they are declared as, so in the debugger, it only sees the value, not the #defined name, e.g. if you have #define NUMBER_OF_CATS 10, in the debugger you'll see only 10 (since the pre-processor has replaced every instance of NUMBER_OF_CATS in your code with 10.
An enumerated type is a type in itself and the values are constant instances of this type, and so the pre-processor leaves it alone and you'll see the symbolic description of the value in the debugger.
The compiler stores enum information in the binary when the program is compiled with certain options.
When a variable is of a enum type, a debugger can show the enum name. This is best shown with an example:
enum E {
ONE_E = 1,
};
int main(void)
{
enum E e = 1;
return 0;
}
If you compile that with gcc -g
you can try out the following 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)
If you used a define, you would not have a proper type to give e
, and would have to use an integer. In that case, the compiler would print 1
instead of ONE_E
.
The -g
flag asks gdb to add debugging information to the binary. You can even see that it is there by issuing:
xxd test | grep ONE_E
I don't think that this will work in all architectures, though.
At least for Visual Studio 2008 which I currently have at hand, this sentence is correct. If you have
#define X 3
enum MyEnum
{
MyX = 3
};
int main(int argc, char* argv[])
{
int i = X;
int j = (int)MyX;
return 0;
}
and you set a breakpont in main
, you can hover your mouse over "MyX" and see that it evaluates to 3. You do not see anything useful if you hover over X.
But this is not a language property but rather IDE behavior. Next versions might do it differently, as well as others IDEs. So just check it out for your IDE to see if this sentence applies in your case.
I am answering too late but i feel i can add something - enum vs. const vs. #define
enum -
- Does not require assining values (if just want to have sequential values 0, 1, 2..) whereas in case of #defines you manually need to manage values which could cause human error sometime
- It works just as variable to during online debugging the value of enum can be watched in watch window
You can have a variable of enum type to which you can assign an enum
typedef enum numbers { DFAULT, CASE_TRUE, CASE_OTHER, };
int main(void) { numbers number = CASE_TRUE; }
const -
- It is constant stored in read only area of memory but can be accessed using address which is not possible in case of #define
- You have type check in your hand if you use const rather than #define
defines are pre-processing directive but const is compile time for example
const char *name = "vikas";
You can access the name and use its base address to read the such as vikas[3] to read 'a' etc.
#defines - are dumb preprocessor directives which does textual replacement
Check the following article, nice summary http://www.queryhome.com/26340/define-vs-enum-vs-constant
精彩评论