What is the difference between a macro and a const in C++?

Solution 1:

Macros and constants are not remotely the same thing, each is sometimes appropriate for the circumstances, and your answer only scratches at the surface of the difference. Also, C++ has two different kinds of constants.

A constant defined with the const qualifier is best thought of as an unmodifiable variable. It has all the properties of a variable: it has a type, it has a size, it has linkage, you can take its address. (The compiler might optimize away some of these properties if it can get away with it: for instance, constants whose address is never used may not get emitted into the executable image. But this is only by the grace of the as-if rule.) The only thing you can't do to a const datum is change its value. A constant defined with enum is a little different. It has a type and a size, but it doesn't have linkage, you can't take its address, and its type is unique. Both of these are processed during translation phase 7, so they can't be anything but an lvalue or rvalue. (I'm sorry about the jargon in the preceding sentence, but I would have to write several paragraphs otherwise.)

A macro has far fewer constraints: it can expand to any sequence of tokens, as long as the overall program remains a well-formed program. It doesn't have any of the properties of a variable. Applying sizeof or & to a macro may or may not do something useful, depending on what the macro expands to. Macros are sometimes defined to expand to numeric literals, and such macros are sometimes thought of as constants, but they're not: "the compiler proper" (that is, translation phase 7) sees them as numeric literals.

It is generally considered good practice, nowadays, not to use a macro when a constant will do. Macros don't obey the same scoping rules as all other identifiers, which can be confusing, and if you use a constant you give more information to translation phase 7 and thus also to the debugger. However, macros permit you to do things that cannot be done any other way, and if you need to do one of those things, you should not hesitate to use them. (Macros that are pulling their weight, in this sense, generally do not just expand to numeric literals, though I am not going to say never.)

EDIT: Here's an example of a macro doing something interesting. It is in no way, shape or form a constant. There may well be a way to get the same effect without a macro (if you know one that doesn't involve stringstreams, I'd be curious to hear about it!) but I think it makes a good illustration of both the power and the danger of macros (for the latter, consider what it would do if it was used outside of one very specific context...)

static double elapsed()
{ ... }
#define ELAPSED '[' << std::fixed << std::setprecision(2) << elapsed() << "] "

// usage:
for (vector<string>::iterator f = files.begin(); f != files.end(); f++) {
    cout << ELAPSED << "reading file: " << *f << '\n';
    process_file(*f);
}

Solution 2:

One should prefer const int sum = 1; over #define sum 1 for a number of reasons:

Scope Based Mechanism:

#defines 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.