为什么我应该在c++中避免使用宏?

Why should I avoid macros in C++?

本文关键字:我应该 c++ 为什么      更新时间:2023-10-16

我读过很多书& &;我应该避免在c++中使用宏。好吧,但为什么呢?我不明白。它们非常有用,经常在c中使用。

谁能(非常)详细地解释一下,为什么我应该在c++中避免使用它们?

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

考虑下面这个众所周知的例子:

#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: %sn", ret, msg); 
        exit(1); 
    }
⋮
if (ready)
    CHECK_ERROR(try_send(packet), "Failed to send");
else
    enqueue(packet);

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

为了避免上述问题(else附加到CHECK_ERRORif而不是外部的if),应该在do … while (false)中包装这样的宏,如下所示(也避免重复的ret):

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

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

长话短说,宏在很多层面上都是危险的,因此应该只在万不得已的时候使用。