Why should I avoid macros in C++? [closed]

2020-01-29 16:45发布

问题:

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 6 years ago.

I have read in many books & tutorials that I should avoid macros in c++. Fine, but why? I don't get it. They are very useful and often used in C.

Could someone explain (very) detailed, why I should avoid them in C++?

回答1:

Macros don't respect scoping rules and operate at the textual level, as opposed to the syntax level. From this arise a number of pitfalls that can lead to strange, difficult to isolate bugs.

Consider the following well-known example:

#define max(a, b) ((a) < (b) ? (b) : (a))
⋮
int i = max(i++, j++);

The preferred alternative in this case is a function template:

template <typename T>
T max(const T & a, const T & b) { return a < b ? b : a; }

Here's another case that leads to subtle problems:

#define CHECK_ERROR(ret, msg) \
    if (ret != STATUS_OK) { \
        fprintf(stderr, "Error %d: %s\n", ret, msg); \
        exit(1); \
    }
⋮
if (ready)
    CHECK_ERROR(try_send(packet), "Failed to send");
else
    enqueue(packet);

You might think that the solution is as simple as wrapping the contents of CHECK_ERROR in { … }, but this won't compile due to the ; before the else.

To avoid the above problem (the else attaching to CHECK_ERROR's if instead of the outer if), one should wrap such macros in do … while (false) as follows:

#define CHECK_ERROR(ret, msg) \
  do { \
    if (ret != STATUS_OK) { \
        fprintf(stderr, "Error %d: %s\n", ret, msg); \
        exit(1); \
    } \
  while (false)

This has no effect on the meaning of the macro, but ensures that the entire block is always treated as a single statement and doesn't interact in surprising ways with if statements.

Long story short, macros are hazardous at many levels and should thus be used only as a last resort.