C++中逻辑运算符子表达式的求值顺序

6

有很多与优先级求值顺序概念相关的问题,但我没有找到一个涉及到我特殊情况的。

请考虑下面的陈述:

if(f(0) && g(0)) {};

是否保证 f(0) 会被先计算?注意运算符是 &&。

我的困惑源于我在 “The C++ Programming Language, (Stroustrup, 4ed, 2013)” 中读到的内容。

该书第10.3.2节中写道:

表达式中子表达式的计算顺序是未定义的。特别地,不能假设表达式从左到右计算。例如:

int x = f(2)+g(3); // 不确定是先调用 f() 还是 g()

这似乎适用于包括 && 运算符在内的所有运算符,但在接下来的一段中它说:

,(逗号)、&&(逻辑与)和 ||(逻辑或)运算符保证它们的左操作数在其右操作数之前被计算。

该书的第11.1.1节中还提到了另一个例子:

&& 和 || 运算符仅在必要时计算其第二个参数,因此它们可以用于控制求值顺序(§10.3.2)。例如:

while (p && !whitespace(p)) ++p;

在此,如果 p 是 nullptr,则不会对其进行解引用。

这个最后的引用暗示了 && 和 || 先计算它们的第一个参数,因此它似乎加强了我对第二个引用是第一个引用的例外的假设,但我也无法从这个最后的例子中得出最终结论,因为该表达式只包含一个子表达式,而不像我的例子一样包含两个。


简而言之,逻辑运算符是特殊情况。 - OMGtechy
我在你的帖子中找不到问题。如果你的问题是关于 fg 哪个先被评估,那么你已经自己回答了。 - Otomo
没有人会相信我,我遇到了这样一个情况 - 如果(expr1 && expr2),expr2先运行。但是之后我没有再遇到过类似的情况。因此,我猜测expr1中有问题,并且它被优化了,所以它没有在最开始运行。但我找不到证明的代码。 - Zhang
2个回答

4
特殊的序列化行为在C和C++中已经被证明,包括&&||,。你引用的第一句话应该是“表达式中子表达式的求值顺序通常是未指定的”或者“除了少数特定情况外,表达式中子表达式的求值顺序是未指定的”。你询问了C++相关问题,但this questionC FAQ list中也是相关的。
补充说明:我刚才意识到,“未指定”这个词在这些规则中比“未定义”的词更好。像 f() + g() 这样的写法不会导致未定义的行为。你只是无法知道 fg 哪个会先被调用。

模糊的答案被接受了。我认为答案可以更简单,如:“是的,对于&&、||和,它是有保证的。”链接也不起作用。 - TonySalimi

3

是的,保证先完全评估f(0)

这是为了支持称为短路的行为,如果第一个函数返回false,我们根本不需要调用第二个函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接