我读了许多书和我应该避免在c ++中使用宏的教程。很好,但为什么呢?我不明白。它们非常有用,通常用于C。
有人可以解释(非常)详细,为什么我应该在C ++中避免它们?
答案 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)
语句进行交互。
长话短说,宏在许多层面都是危险的,因此只能作为最后的手段使用。