C++ 移位运算符优先级奇怪
考虑以下代码:
typedef vector<int> intVec;
intVec& operator<<(intVec& dst, const int i) {
dst.push_back(i);
return dst;
}
int intResult0() {
return 23;
}
int intResult1() {
return 42;
}
// main
intVec v;
v << intResult0() << intResult1();
奇怪的是,编译器生成代码,该代码评估 intResult1
BEFORE intResult0
(使用最新的 VC 和 gcc 进行测试) 。 为什么编译器要这样做? 通过这样做,各个值的评估和使用之间的时间(不必要地)增加了(?),即首先获取 42,但最后推送到向量。 C++ 标准是否规定了这一点?
Consider the following code:
typedef vector<int> intVec;
intVec& operator<<(intVec& dst, const int i) {
dst.push_back(i);
return dst;
}
int intResult0() {
return 23;
}
int intResult1() {
return 42;
}
// main
intVec v;
v << intResult0() << intResult1();
The weird thing is, that the compiler generates code, which evaluates intResult1
BEFORE intResult0
(tested with newest VC und gcc).
Why would the compiler do this? By doing so, the time between evaluation and usage of the respective values is (unnecessarily) increased(?), i.e. 42 is fetched first, but pushed last to the vector.
Does the C++ standard dictate this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
两个序列点之间的子表达式的求值顺序未定义。
上面的代码是语法糖:
编译器唯一的约束是它必须在调用方法之前评估所有参数并遵守优先级规则。 但只要遵循这些规则,每个实现都可以选择细节,因此这个顺序可能会在编译器之间发生变化。
在此示例中:
请参阅此处了解更多信息:
什么是C++ 程序员应该了解的所有常见未定义行为?
和
C++ 程序员应该了解哪些常见的未定义行为?
The order of evaluation of sub-expressions between two sequence point is undefined.
The above code is syntactic sugar for:
The only constraint the compiler has, is that it must evaluate all parameters before a method is called and obey the precedence rules. But as long as it follows these rules each implementation is allowed to choose the details and as such this order may change between compilers.
In this example:
See here for more info:
What are all the common undefined behaviours that a C++ programmer should know about?
and
What are all the common undefined behaviours that a C++ programmer should know about?
根据 Stroustrup 第 6.2.2 节:
According to Stroustrup section 6.2.2:
这与优先级无关。
最后一条语句中没有序列点,因此编译器可以自由地按其喜欢的任何顺序计算子表达式,只要在组合子表达式时使用优先级即可。
请注意,优先级不定义求值的整体顺序 - 它只是定义如何组合具有多个运算符的表达式的操作数。
例如,在以下表达式中:
在某些时候,编译器需要先计算
(a() * b())
,然后再添加c()
的结果,但没有说明每个函数调用需要执行什么顺序。 编译器可以很容易地决定首先调用c()
,将结果压入堆栈,然后执行任何需要执行的操作来评估(a() * b())< /code> 表达式(在这种情况下,它可能决定首先评估
b()
)。优先级所起的唯一作用是不允许编译器将表达式计算为:
This has nothing to do with precedence.
There is no sequence point in that last statement, so the compiler is free to evaluate the sub-expressions in whatever order it likes as long as precedence is used when combining the sub-expressions.
Note that precedence does not define an overall order of evaluation - it just defines how the operands of an expression with several operators will be combined.
For example, in the following expression:
at some point, the compiler would need to evaluate
(a() * b())
before adding in the result ofc()
, but there's nothing that says what order each individual function call needs to be made. The compiler can quite easily decide to callc()
first, push the result on a stack, then do whatever it needs to do to evaluate the(a() * b())
expression (in which case, it might decide to evaluateb()
first).The only role that precedence plays is that the compiler is not permitted to evaluate the expression as:
C++ 标准,5:4
The C++ Standard, 5:4