Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

All over the Internet I see people advocating for the use of enum or const rather than #define for constant definition.

Are there times when #define is more appropriate or equally appropriate? Please explain.

Are there times when #define is just awful? Please elaborate. (You can say 'always' if you really wish, but I'm looking for more specific answers.)

(Yes, I am trying to justify my use of #define, which to me looks so much neater.)

share|improve this question
add comment

4 Answers

up vote 7 down vote accepted

To keep it simple: they're right and you're wrong.

There's rarely a good reason to use #define for a constant in C++. Yes, they're pretty awful. In particular, they completely ignore the scopes for normal identifiers, and instead always have file scope.

You can work around that (e.g., using prefixes on names you define to avoid collisions) but even at best they don't fit very well with the rest of the language.

I suspect you're thinking it looks neater is more a matter of habituation than any intrinsic superiority -- when I first started moving from C to C++ I tended to feel the same way. Purely intellectually I could understand the points being raised, but emotionally they just seemed wrong. For a while I considered it kind of silly to change something that had worked find forever. I had to really force myself to use const instead, and at first didn't really believe in it -- but fairly quickly I not only got used to it, but ended up admitting that it really was better.

share|improve this answer
    
see my question in david's comments about optimization. –  Matthieu Apr 22 '11 at 17:59
1  
@Matthieu: I would not normally expect any difference in optimization. It's hard to say some compiler somewhere couldn't possibly show a difference under some circumstances, but if so it would be a fairly unusual exception. –  Jerry Coffin Apr 22 '11 at 18:03
    
Thank you. You have convinced me enough to at least give it a go, and so far it's not that bad. ;) –  yodie Apr 22 '11 at 19:40
add comment

In C, you often have to use #define. In C++, you can avoid it.

The problem with #define is that it's a textual substitution that has file scope. It's not possible to limit its scope. If you want two different #defines for different parts of the program, you can't put them in different namespaces. If you're #includeing different header files with different values for a #define, you have to make sure you get the order right. If you do a #define of something that's not obviously a value (like all-caps), you run the risk of breaking people's programs in weird ways.

So, if you submitted a code review and I saw an unnecessary #define, I'd ask it to be changed, and perhaps submit it as a defect.

share|improve this answer
    
Do you know if there is any impact on compiler optimization ? I often heard about possible missed compiler optimization when using define instead of const, but cannot find any sources to confirm or infirm that theory ? –  Matthieu Apr 22 '11 at 17:58
    
@Matthieu: A #define is a textual substitution, while a const is a variable with a value. I suppose it would depend on whether the compiler could precompute the value or not. If not possible (maybe there's a function call), the program might have to evaluate the expression multiple times. That's all that's coming to mind right now. –  David Thornley Apr 22 '11 at 18:15
add comment

#define is part of the pre-compiler and should be treated as such. It should only be used to change the behavior of the compiler based on options you are passing to it (debug option or platform option for example), and more generally conditional compilation.

Using #define for constants that are used in-code effectively creates a new keyword that breaks any encapsulation (such as namespaces). reference : C++FAQ. That breach of encapsulation wich is a basic OO concept is the main reason why defines are not popular for constants definition in C++.

share|improve this answer
add comment

I guess I'm a little old school in considering NAMESPACE_CONSTANT to be not much different than Namespace::CONSTANT semantically. While the former technically has a larger scope and is not in enforced separate namespaces supported by the compiler, in practice it can usually be considered as such, and clashes are almost always easily noticed and fixed. The define method would not still be used by so many people if it didn't work in complex software.

The problem is it often leads to REALLY_LONG_NAMESPACE_PREFIXES_FOR_EACH_VALUE, whereas you can often leave off the namespace for even common constant names with the newer method. This gives a big boost to readability.

The other benefit I haven't seen mentioned yet is that using an enum gives you compiler type checking. That's a big help if a "constant" has different values in different contexts, which happens more often than I'd like when working in a middle layer. Again, you can easily work around namespace clashes here by adding prefixes to your defines, but the compiler won't tell you if you use the wrong prefix in a function call.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.