为什么内置类型的链式前缀递增/递减不是 UB 表示C++
Why chained prefix increment/decrement for builtin type is not UB for C++?
在前缀增量 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
}
相关文章:
- 'string.assign(string.data(), 5)' 是明确定义的还是 UB?
- 使用 CTRP 时,是否访问访问父构造函数 UB 中的子属性?
- 为什么我会收到此错误?无法将 {lb, ub} 从<大括号括起来的初始值设定项列表>转换为 float(**)(float*, int)
- 将空*参数转换为各种类型的参数是UB吗?
- 通过指针恢复对数组的引用.UB与否?
- 传递给放置 new 的指针是否是指向其对象表示形式的非 UB 指针?
- 在未初始化的变量上使用复合赋值运算符(+=, ..)不是C++中的UB?
- 使用lock_guard采用的互斥锁会导致 UB 吗?
- 模板与常规函数歧义 - UB?
- 是否通过单元化指针UB访问静态类成员
- 是否可以默认使用UB
- QString::utf16(): Is it UB or not?
- 创建自己的owner_ptr类;在传递堆栈或静态分配的地址时如何避免UB?
- 当原始数据是常量时,修改指针指向的位置是 UB 吗?
- 为什么删除void*是UB而不是编译错误?
- C++ - 使用常量引用来延长临时成员,确定还是 UB?
- 在条件运算符中使用对象两次会产生 UB 吗?
- 是否有任何编译器标志可以在下面的代码中用于报告有关 UB 的警告?
- 模板对象的C 数组:施放到常见的非类型模板参数是UB吗?
- 通过reinterpret_casting方法指针从指针调用派生类的方法。这是 UB 吗?