什么是双重评估,为什么要避免它?

2022-01-11 00:00:00 macros c++ preprocessor-directive

我是在 C++ 中使用宏来阅读的,比如

I was reading that in C++ using macros like

#define max(a,b) (a > b ? a : b)

可能导致双重评估".谁能给我一个例子,说明何时发生双重评估以及为什么它不好?

can result in a 'double evaluation'. Can someone give me an example of when a double evaluation occurs and why it's bad?

PS:令人惊讶的是,除了 Clojure 中的示例(其中我不明白).

P.S.: Surprisingly I couldn't find any detailed explanation when googling for it except for an example in Clojure (which I can't understand).

推荐答案

想象一下你是这样写的:

Imagine you wrote this:

#define Max(a,b) (a < b ? b : a)

int x(){ turnLeft();   return 0; }
int y(){ turnRight();  return 1; }

然后这样称呼它:

auto var = Max(x(), y());

你知道 turnRight() 会被执行两次吗?该宏,Max 将扩展为:

Do you know that turnRight() will be executed twice? That macro, Max will expand to:

auto var = (x() < y() ? y() : x());

在评估条件后 x() <y(),然后程序在 y() : x() 之间进行所需的分支:在我们的例子中是 true,它调用 y() 第二次.看看 Live On Coliru.

After evaluating the condition x() < y(), the program then takes the required branch between y() : x(): in our case true, which calls y() for the second time. See it Live On Coliru.

简单地说,将 表达式 作为参数传递给您的 类函数宏, Max 可能会对该表达式求值两次,因为该表达式将在宏定义中使用宏参数的任何地方重复.请记住,宏由 预处理器处理.

Simply put, passing an expression as an argument to your function-like macro, Max will potentially evaluate that expression twice, because the expression will be repeated where ever the macro parameter it takes on, is used in the macro's definition. Remember, macros are handled by the preprocessor.

所以,底线是,不要仅仅因为你希望它是通用而使用宏来定义函数(在这种情况下实际上是一个表达式),而使用函数可以有效地完成它模板

So, bottom line is, do not use macros to define a function (actually an expression in this case) simply because you want it to be generic, while it can be effectively done using a function templates

PS:C++ 有一个 std::max 模板函数.

PS: C++ has a std::max template function.

相关文章