从技术上讲,总的来说这是Undefined Behavior。
但是,答案有两个重要方面。
代码声明:
std::cout << a++ << a;
被评估为:
std::operator<<(std::operator<<(std::cout, a++), a);
该标准没有定义函数参数的评估顺序。
所以要么:
std::operator<<(std::cout, a++)
首先评估或
a
首先评估或
- 它可能是任何实现定义的顺序。
根据标准,此订单未指定[参考 1]。
[参考 1] C++03 5.2.2 函数调用
第 8 段
参数的评估顺序未指定。参数表达式评估的所有副作用在输入函数之前生效。后缀表达式和参数表达式列表的求值顺序未指定。
此外,在对函数的参数求值之间没有序列点,但序列点仅在对所有参数进行求值后才存在[Ref 2]。
[参考 2] C++03 1.9 程序执行 [intro.execution]:
第 17 段:
调用函数时(无论函数是否内联),在对所有函数参数(如果有)求值之后都会有一个序列点,该序列点发生在函数体中的任何表达式或语句执行之前。
请注意,这里的值c
被多次访问而没有中间序列点,关于这个标准说:
[参考 3] C++03 5 表达式 [expr]:
第 4 段:
....
在前一个和下一个序列点之间,一个标量对象的存储值最多只能通过表达式的评估修改一次。此外,只能访问先验值以确定要存储的值。对于完整表达式的子表达式的每个允许排序,都应满足本段的要求;否则行为未定义。
代码c
在不干预序列点的情况下多次修改,并且没有被访问以确定存储对象的值。这明显违反了上述条款,因此标准规定的结果是未定义行为[参考 3]。