为什么我要避免使用C ++中的宏?

时间:2013-06-11 11:34:27

标签: c++ macros

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

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

1 个答案:

答案 0 :(得分:11)

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

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

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

您可能认为解决方案就像在CHECK_ERROR中包含{ … }的内容一样简单,但由于;之前的else而无法编译

要避免上述问题(else附加到CHECK_ERROR的{​​{1}}而非外部if),应该将这些宏包装在{{1}中如下:

if

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

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