if(a && b)
{
do something;
}
是否有可能从右到左评估参数(b -> a)?
如果“是”,什么影响评估顺序?
(我使用的是VS2008)
在 C++ 中,只有少数运算符可以保证计算顺序
operator &&
首先评估左操作数,如果该值在逻辑上是 false
,那么它会避免评估右操作数。典型用途例如 if (x > 0 && k/x < limit) ...
可以避免被零除的问题。
operator ||
首先评估左操作数,如果该值在逻辑上是 true
,那么它会避免评估右操作数。例如,当设置标志 if (overwrite_files || confirm("File existing, overwrite?")) ...
时,overwrite_files
不会询问确认。
operator ,
首先计算左操作数,然后计算右操作数,返回右操作数的值。该运算符不经常使用。请注意,函数调用中参数之间的逗号是not逗号运算符,并且不保证计算的顺序。
三元运算符
x?y:z
首先计算x
,然后根据结果的逻辑值仅计算y
或仅计算z
。
对于所有其他运算符,未指定求值顺序。
情况实际上更糟,因为不是没有指定顺序,而是表达式根本没有“顺序”,例如在
std::cout << f() << g() << x(k(), h());
函数可能会按照
h-g-k-x-f
的顺序调用(这有点令人不安,因为 <<
运算符的心智模型以某种方式传达了顺序性的概念,但实际上仅按照将结果放在流,而不是按照计算结果的顺序*)。
显然表达式中的值依赖可能会引入一些顺序保证;例如,在上面的表达式中,保证
k()
和 h()
都将在 x(...)
之前被调用,因为调用 x
需要两者的返回值(C++ 不是 lazy)。
另请注意,
&&
、||
和 ,
的保证仅对预定义运算符有效。如果您为您的类型重载这些运算符,那么在这种情况下它们将像正常的函数调用一样,并且操作数的求值顺序将是未指定的。
C++17 引入了一些关于计算顺序的额外临时特定保证(例如在左移运算符
<<
中)。有关所有详细信息,请参阅https://stackoverflow.com/a/38501596/320726
评估顺序由标准规定,为
left-to-right
。最左边的表达式始终首先使用 &&
子句进行求值。
如果您希望首先评估
b
:
if(b && a)
{
//do something
}
如果两个参数都是方法,并且您希望对它们进行求值,而不管它们的结果如何:
bool rb = b();
bool ra = a();
if ( ra && rb )
{
//do something
}
在这种情况下,由于您使用的是
&&
,因此总是首先计算 a
,因为结果用于确定是否短路表达式。
如果
a
返回 false,则 b
根本不允许评估。
内置逻辑 AND 运算符 && 和内置逻辑 OR 运算符 || 的第一个(左)参数的每个值计算和副作用在第二个(右)参数的每个值计算和副作用之前排序。
请阅读此处,了解规则集的更详尽解释: 订单评价
它将从左到右评估,并在可以的情况下短路评估(例如,如果 a 评估为 false,则不会评估 b)。
如果您关心它们的评估顺序,您只需在 if 语句中按照所需的评估顺序指定它们。
内置
&&
运算符始终首先计算其左操作数。例如:
if (a && b)
{
//block of code
}
如果
a
是false
,那么b
将不会被评估。
如果您希望首先计算
b
,并且仅当 a
为 true 时才计算 b
,只需以相反的方式编写表达式即可:
if (b && a)
{
//block of code
}