为什么内置类型的链式前缀递增/递减不是 UB 表示C++

Why chained prefix increment/decrement for builtin type is not UB for C++?

本文关键字:UB C++ 表示 置类型 为什么 前缀 内置      更新时间:2023-10-16

在前缀增量 cpprefernce.com 示例中,有这样的代码:

int n1 = 1;
...
int n3 = ++ ++n1;

为什么在这种情况下链式增量不会导致 UB?在这种情况下,最多修改一次的规则是不违反的吗?

在 C++11 及更高版本中,当有两个未排序的写入或一个写入和一个读取未排序并访问相同的内存位置时,会发生 UB。但是++x等价于x+=1,所以++ ++n1等价于(n1+=1)+=1,这里读写因为赋值和复合赋值算子的属性,是严格顺序发生的:先读取n1,再写入一加原值,再读取结果值, 然后写回一个加该值。

在 C++03 中,这是 UB,因为您提到的旧规则:两个修改之间没有序列点。但在 C++11 中,不再有任何序列点;取而代之的是"先于排序"的部分顺序。

参见布莱恩的回答,了解更简单的术语,.

这是法律原因,C++标准是这么说的,重点是我的......按照C++14草案进行

5.3.2 递增和递减

前缀 ++ 的操作数通过加 1 进行修改,或者设置为 true,如果 是布尔值(此用法已弃用)。操作数应为可修改 左值。操作数的类型应为算术类型或 指向完全定义的对象类型的指针。结果是 更新的操作数;它是一个左值,它是一个位字段,如果 操作数是一个位字段。如果 x 不是布尔类型,则表达式 ++x 相当于 x+=1

所以,这是完全合法的

#include <iostream>
using namespace std;
int main(){
    int x =8;
    int y = ++ ++ ++ ++ ++ ++ ++ ++ x;
    cout << x << " " << y;
}

输出

16 16

1.9 程序执行

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
}