I was asked this question in a technical interview:
What is the difference between a
const
and a macro in C++?
My answer was that a macro is a preprocessor directive and it could be difficult to debug the application if you use a macro since it is replaced with the constant expression before compilation, whereas a const
can have a type identifier and is easy to debug.
Could anyone point out any other difference and which should be preferred?
EDIT:
From the IBM documentation for C++:
The following are some differences between
#define
and theconst
type qualifier:
The
#define
directive can be used to create a name for a numerical, character, or string constant, whereas a const object of any type can be declared.A const object is subject to the scoping rules for variables, whereas a constant created using
#define
is not. Unlike aconst
object, the value of a macro does not appear in the intermediate source code used by the compiler because they are expanded inline. The inline expansion makes the macro value unavailable to the debugger.A macro can be used in a constant expression, such as an array bound, whereas a
const
object cannot. (I think we surely need to use macro to definearray_size
.The compiler does not type-check a macro, including macro arguments.
Macros don't respect scope, and a macro's name may not be available to a symbolic debugger. Dan Saks has a fairly complete article on the relative merits of macros (none), constant objects, and enumeration constants. Like Stephen Dewhurst, Saks prefers enumeration constants for integer values since they take up no storage (more precisely, enumeration constants have neither storage duration nor linkage).
A macro always have a type, for instance,
#define FIVE 5
is of type int.An advantage for the const variable over the macro could be the memory usage : With a macro the value may have to be duplicated everywhere it is used will a const variable will not be duplicated in memory. (but I am not sure of this difference)
Another difference is that a
const
variable has a memory and can be referenced by a pointer. Macro is just the autocomplete that will happen before compilation, hence the name is lost during compiling.Also macro can be just more than a constant. It can be am expression or anything that is syntactically correct, even a whole definition of a function.
Macros are used to depict programming choices e.g. stack size; while
cosnt
is used to depict the real world constants like value of Pi or e.define can be redefine , but const will be cause compiler error:
sample: source : main.cpp
One should prefer
const int sum = 1;
over#define sum 1
for a number of reasons:Scope Based Mechanism:
#define
s don't respect scopes so there is no way to create a class scoped namespace. While const variables can be scoped in classes.Avoiding Weird magical numbers during compilation errors:
If you are using
#define
those are replaced by the pre-processor at time of precompilation So if you receive an error during compilation, it will be confusing because the error message wont refer the macro name but the value and it will appear a sudden value, and one would waste lot of time tracking it down in code.Ease of Debugging:
Also for same reasons, while debugging
#define
would provide no help really.To avoid both above situations
const
will be a better choice.( Originally posted for static const vs #define - reproducing here as this question seems to have more "momentum"... let me know if that's inappropriate... )
Pros and cons to everything, depending on usage:
#define
ala#define S std::string("abc")
, but the constant avoids repeated construction of distinct temporaries at each point of use#define X "x"
and some client usage ala"pre" X "post"
, you're in trouble if you want or need to make X a runtime-changeable variable rather than a constant, whereas that transition is easier from aconst char*
orconst std::string
given they already force the user to incorporate concatenation operations.{ 1, 2 }
that can be used to initialise arrays, or#define MICROSECONDS *1E-6
etc. (definitely not recommending this!)__FILE__
and__LINE__
can be incorporated into the macro substitutiontemplate <typename T> void f(T t) { cout << ++t; }
won't compile)template <typename T> void f(T)
get a distinct instantiation when passed the same numeric value from different enums, all of which are distinct from any actual f(int) instantiation.As a general rule, I use consts and consider them the most professional option for general usage (though the others have a simplicity appealing to this old lazy programmer).