2011-10-28 99 views
31
if(a && b) 
{ 
    do something; 
} 

有没有可能评估从右到左的参数(b - > a)?“IF”论证评价令?

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

(我使用VS2008)

+9

'如果(B && A)'会为你做它。 –

+1

什么是'a'和'b'? –

+0

试试如果(b && a)。试试这个链接:http://msdn.microsoft.com/en-us/library/2bxt6kc4.aspx – CloudyMarble

回答

37

评估订单由标准指定,并且是left-to-right。最左边的表达式总是首先用&&子句进行评估。

如果你想b先计算:

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

如果两个参数的方法,你想他们都进行评估,不论其结果是:

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

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

这是一种解脱......因为一旦C++拥有正确的默认行为,而不是令人惊讶的模糊的行为 –

+3

@AviadRozenhek:你有权害怕,因为确实有可能在表达式'a'之前评估表达式'b'。为此,操作符不能是预定义的&&逻辑运算符,而是用户定义类型的重载。在这种情况下,对参数的评估顺序是未指定的(甚至比你甚至不能期待实际顺序更重要,因为评估甚至可能是“混合”的:有点“a”,然后是“b”,然后是更多'a',然后再一些'b'的剩余位,最后调用自定义运算符)。 – 6502

+0

如果使用'||'代替,情况如何?它应该保持不变,除非一些编译器优化gun it iu,正确@ 6502? – mdw7326

7

在这种情况下,因为您使用&&a将总是被第一,因为使用该结果来确定是否要短路的表达进行评价。

如果a返回false,则不允许b评估。

+1

...除非运算符&&超载。这是可能的,但被认为是糟糕的设计。 – dalle

+0

我没有想到这一点。好点子。 :) – Mysticial

+0

我很肯定,以下是这种情况,但这样做是否安全: 'Obj * obj; if(obj && obj-> foo()){...} 我假设它检查是否obj不是NULL,只有当它不是NULL时,它才会检查obj-> foo()的结果,对? –

2

它将从左到右进行评估,如果评估结果可以将评估短路(例如评估结果为false,则评估结果为b)。

如果你关心他们在你评估的顺序,你只需要在你的if语句中以所需的评估顺序指定它们。

+0

问题是关于C++,而不是C#(尽管你可能是正确的,它们都做同样的事情,受C的启发)。 –

+0

哎呀!我认为他们都和你说的一样。 –

44

用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()); 

它可能是功能将以h-g-k-x-f的顺序被调用(这有点令人不安,因为<<操作员的心智模型以某种方式传达了序列性的想法,但实际上只考虑序列中的结果放在流上的顺序,而不是结果的顺序计算)。

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

还请注意,&&||,的保证仅对预定义的操作员有效。如果你为你的类型重载这些运算符,那么它们就像正常的函数调用一样,并且操作数的评估顺序将不确定。

+1

只是一个黑客,但价值依赖也强加一个订单。在“(a + b)* c”这样的表达式中,必须在加法之前评估“a”和“b”,并且加法必须在乘法之前进行。通常,这种效果是不可观察的,但是如果运算符超载,它可能是可见的。 –

+0

@JamesKanze:好的。我认为对于像C++这样的语言来说这很明显,但无论如何都会添加一个注释。 – 6502

3

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

这里阅读的设置的规则更详尽的解释: order evaluation

1

&&运营商总是先计算其左操作数。例如:

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

如果a是假的,那么b将无法​​进行评估。

如果你想b首先要评估,a只有b是真实的,简单的写表达的其他方式:

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