C++ 编译器优化和短路评估

C++ compiler optimizations and short-circuit evaluation

这是我的代码:

b = f() || b;

函数f()有副作用,必须一直执行。通常,只有正确的操作数可以短路,这段代码应该可以工作。但恐怕有些编译器会颠倒这两个操作数,因为短路函数评估比简单的变量评估更有效。我知道 g++ -O3 会破坏一些规范,但我不知道这段代码是否会受到影响。

那么,我的代码没有风险吗?

我知道 Is short-circuiting logical operators mandated? And evaluation order? 但我的问题是关于编译器优化,我不知道他们不能违反标准(即使这会很奇怪)。

But I am afraid some compilators reverse the two operands

这些表达式必须从左到右求值。这包含在有关运算符 &&||?, 的标准中。他们特别提到顺序,以及强制顺序点。

§5.14.1(逻辑与)

The && operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). The result is true if both operands are true and false otherwise. Unlike &, && guarantees left-to-right evaluation: the second operand is not evaluated if the first operand is false.

§5.15.1(逻辑或)

The || operator groups left-to-right. The operands are both contextually converted to bool (Clause 4). It returns true if either of its operands is true, and false otherwise. Unlike |, || guarantees left-to-right evaluation; moreover, the second operand is not evaluated if the first operand evaluates to true.

§5.16.1(条件运算符)

Conditional expressions group right-to-left. The first expression is contextually converted to bool (Clause 4). It is evaluated and if it is true, the result of the conditional expression is the value of the second expression, otherwise that of the third expression. Only one of the second and third expressions is evaluated. Every value computation and side effect associated with the first expression is sequenced before every value computation and side effect associated with the second or third expression.

§5.19.1(逗号运算符)

The comma operator groups left-to-right. A pair of expressions separated by a comma is evaluated left-to-right; the left expression is a discarded value expression (Clause 5). Every value computation and side effect associated with the left expression is sequenced before every value computation and side effect associated with the right expression. The type and value of the result are the type and value of the right operand; the result is of the same value category as its right operand, and is a bit-field if its right operand is a glvalue and a bit-field. If the value of the right operand is a temporary (12.2), the result is that temporary.

关于您对违反此顺序的优化的担忧,编译器不允许更改顺序。编译器必须首先(尝试)遵循标准。 然后他们可以尝试使您的代码更快。他们可能不会仅仅为了性能而违反标准。这破坏了拥有标准的整个前提。

标准明确规定了优化代码的行为"as-if"只要您只依赖于标准行为,这正是编写的代码。

由于标准要求从左到右评估布尔语句,因此任何(兼容)优化都不能更改评估顺序。