"IF"论证评估顺序?

win*_*rrr 37 c++ if-statement operator-precedence

if(a && b)
{
  do something;
}
Run Code Online (Sandbox Code Playgroud)

有没有可能从右到左评估论点(b - > a)?

如果"是",影响评估顺序的是什么?

(我正在使用VS2008)

650*_*502 56

使用C++,只有少数运算符可以保证评估顺序

  • operator &&首先计算左操作数,如果该值是逻辑上的,false则它避免评估右操作数.典型的用途是例如if (x > 0 && k/x < limit) ...避免零除问题.

  • operator ||首先计算左操作数,如果该值是逻辑上的,true则它避免评估右操作数.例如if (overwrite_files || confirm("File existing, overwrite?")) ...,在overwrite_files设置标志时不会询问确认.

  • operator ,首先计算左操作数,然后再计算右操作数,返回右操作数的值.不经常使用此运算符.请注意,函数调用中参数之间的逗号不是逗号运算符,并且不保证评估顺序.

  • 三元运算符首先x?y:z求值x,然后根据结果的逻辑值仅计算y或仅计算z.

对于所有其他运营商,未指定评估顺序.

这种情况实际上更糟,因为并不是没有指定订单,而是根本没有表达式的"订单",例如

std::cout << f() << g() << x(k(), h());
Run Code Online (Sandbox Code Playgroud)

可能会按顺序调用函数h-g-k-x-f(这有点令人不安,因为<<运算符的心智模型以某种方式表达了顺序性的想法,但实际上只是在顺序中将顺序结果放在流上而不是按顺序排列计算结果).

显然,表达式中的值依赖性可能会引入一些顺序保证; 例如,在上面的表达式中,它保证了之前k()h()之前都会被调用,x(...)因为需要调用两者的返回值x.

还要注意保证&&,||并且,仅对预定义的运算符有效.如果为类型重载这些运算符,它们就像正常的函数调用一样,并且操作数的评估顺序将是未指定的.

  • 只是一个问题,但值依赖性也强加了一个顺序。在像“(a + b) * c”这样的表达式中,“a”和“b”必须在加法之前求值,并且加法必须在乘法之前发生。一般来说,这种影响是不可观察到的,但如果运算符超载,则可能是可见的。 (2认同)

Luc*_*ore 45

评估订单由标准指定,并且是left-to-right.最左边的表达式将始终首先使用该&&子句进行计算.

如果您想b先评估:

if(b && a)
{
  //do something
}
Run Code Online (Sandbox Code Playgroud)

如果两个参数都是方法,并且您希望无论结果如何都要对它们进行评估:

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

if ( ra && rb )
{
  //do something
}
Run Code Online (Sandbox Code Playgroud)

  • 这是一种解脱......因为一旦c ++具有正确的默认行为而不是令人惊讶的模糊行为 (8认同)
  • @AviadRozenhek:你害怕是正确的,因为在表达式'a`之前,表达式'b`的确是可能的.但要发生这种情况,操作符不能是预定义的`&&`logical-and运算符,而是用户定义类型的重载.在那种情况下,参数的评估顺序是未指定的(并且甚至比你甚至不能指望实际的排序更糟糕,因为评估甚至可以"混合":一点'a`,然后一些'b`,然后更多的是'a`,然后是'b`的剩余部分,最后调用自定义运算符). (3认同)
  • @ mdw7326 || 也会短路-如果第一个条件为真,则第二个条件将不会得到评估。这不是编译器优化,它是标准要求的。 (2认同)

Mys*_*ial 7

在这种情况下,由于您正在使用&&,a将始终首先进行评估,因为结果用于确定是否使表达式短路.

如果a返回false,则b根本不允许评估.