在 cpprefernce.com前缀增量的示例中,有这样的代码:
int n1 = 1;
...
int n3 = ++ ++n1;
为什么在这种情况下链式增量不会导致 UB?在这种情况下是否违反了最多一次修改的规则?
在 cpprefernce.com前缀增量的示例中,有这样的代码:
int n1 = 1;
...
int n3 = ++ ++n1;
为什么在这种情况下链式增量不会导致 UB?在这种情况下是否违反了最多一次修改的规则?
在 C++11 及更高版本中,当有两次写入或一次写入和一次读取未排序并访问相同的内存位置时,就会发生 UB。but++x
等价于x+=1
, so++ ++n1
等价于(n1+=1)+=1
, 由于赋值和复合赋值运算符的特性,这里的读取和写入以严格的顺序发生:首先n1
读取,然后写入原始值的加一,然后结果值为再次读取,然后将该值的一加一写回。
在 C++03 中,这是UB,因为您提到的旧规则:两个修改之间没有序列点。但是在 C++11 中不再有任何序列点;取而代之的是“先排序”的部分顺序。
有关更简单的术语,请参见Brian 的答案。
这是合法的,因为 C++ 标准是这样说的,重点是我的……按照 C++14 草案进行
5.3.2 递增和递减[expr.pre.incr]
前缀 ++ 的操作数通过加 1 来修改,或者如果它是 bool 则设置为 true(不推荐使用此用法)。操作数应为可修改的左值。操作数的类型应为算术类型或指向完全定义的对象类型的指针。结果是更新的操作数;它是一个左值,如果操作数是一个位域,它就是一个位域。如果 x 不是 bool 类型,则表达式 ++x 等价于 x+=1
所以,这是完全合法的
#include <iostream>
using namespace std;
int main(){
int x =8;
int y = ++ ++ ++ ++ ++ ++ ++ ++ x;
cout << x << " " << y;
}
输出
16 16
1.9 程序执行 [intro.execution]
15 ...如果标量对象的副作用相对于同一标量对象的另一个副作用或使用相同标量对象的值的值计算是无序的,则行为未定义。...
并附有示例:
void f(int, int);
void g(int i, int* v) {
i = v[i++]; // the behavior is undefined
i = 7, i++, i++; // i becomes 9
i = i++ + 1; // the behavior is undefined
i = i + 1; // the value of i is incremented
f(i = -1, i = -1); // the behavior is undefined
}