Why should I avoid macros in C++?

Dav*_*log 5 c++ macros

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++?

Mar*_*tos 11

与语法级别相反,宏不遵守作用域规则并在文本级别操作.由此产生的一些陷阱可能导致奇怪的,难以隔离的错误.

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

#define max(a, b) ((a) < (b) ? (b) : (a))
?
int i = max(i++, j++);
Run Code Online (Sandbox Code Playgroud)

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

template <typename T>
T max(const T & a, const T & b) { return a < b ? b : a; }
Run Code Online (Sandbox Code Playgroud)

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

#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);
Run Code Online (Sandbox Code Playgroud)

您可能认为解决方案就像包装CHECK_ERRORin 的内容一样简单{ … },但由于;之前的原因,这将无法编译else.

为了避免上述问题(else附加到CHECK_ERROR's if而不是外部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)
Run Code Online (Sandbox Code Playgroud)

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

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

  • @Davlog:想想宏是如何扩展的:`max(i ++,j ++)`⇒`((i ++)<(j ++)?(j ++):( i ++))`.注意无论哪个变量是高端最终增加两次.这是宏执行文本替换这一事实的基本问题. (5认同)