“IF”参数评估顺序?

问题描述 投票:0回答:6
if(a && b)
{
  do something;
}

是否有可能从右到左评估参数(b -> a)?

如果“是”,什么影响评估顺序?

(我使用的是VS2008)

c++ if-statement operator-precedence
6个回答
90
投票

在 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 以来的变化

C++17 引入了一些关于计算顺序的额外临时特定保证(例如在左移运算符

<<
中)。有关所有详细信息,请参阅https://stackoverflow.com/a/38501596/320726


61
投票

评估顺序由标准规定,为

left-to-right
。最左边的表达式始终首先使用
&&
子句进行求值。

如果您希望首先评估

b

if(b && a)
{
  //do something
}

如果两个参数都是方法,并且您希望对它们进行求值,而不管它们的结果如何:

bool rb = b();
bool ra = a();

if ( ra && rb )
{
  //do something
}

8
投票

在这种情况下,由于您使用的是

&&
,因此总是首先计算
a
,因为结果用于确定是否短路表达式。

如果

a
返回 false,则
b
根本不允许评估。


4
投票

内置逻辑 AND 运算符 && 和内置逻辑 OR 运算符 || 的第一个(左)参数的每个值计算和副作用在第二个(右)参数的每个值计算和副作用之前排序。

请阅读此处,了解规则集的更详尽解释: 订单评价


2
投票

它将从左到右评估,并在可以的情况下短路评估(例如,如果 a 评估为 false,则不会评估 b)。

如果您关心它们的评估顺序,您只需在 if 语句中按照所需的评估顺序指定它们。


2
投票

内置

&&
运算符始终首先计算其左操作数。例如:

if (a && b)
{
   //block of code
}

如果

a
false
,那么
b
将不会被评估。

如果您希望首先计算

b
,并且仅当
a
为 true 时才计算
b
,只需以相反的方式编写表达式即可:

if (b && a)
{
   //block of code
}
© www.soinside.com 2019 - 2024. All rights reserved.