7

我已经阅读了许多书籍和教程,我应该避免在 C++ 中使用宏。很好,但为什么呢?我不明白。它们非常有用,经常在 C 中使用。

有人可以(非常)详细地解释一下,为什么我应该在 C++ 中避免使用它们?

4

1 回答 1

12

宏不尊重范围规则,而是在文本级别操作,而不是在语法级别。由此产生了许多可能导致奇怪的、难以隔离的错误的陷阱。

考虑以下众所周知的示例:

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

在这种情况下,首选的替代方法是函数模板:

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

这是另一个导致微妙问题的案例:

#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);

您可能认为解决方案就像包装 in 的内容一样简单CHECK_ERROR{ … }但是由于;之前的else.

为避免上述问题(else附加到CHECK_ERROR'sif而不是外部if),应将此类宏包装do … while (false)如下:

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

这对宏的含义没有影响,但确保整个块始终被视为单个语句,并且不会以令人惊讶的方式与if语句交互。

长话短说,宏在许多层面都是危险的,因此只能作为最后的手段使用。

于 2013-06-11T11:40:38.783 回答