Sha*_*our 62 c++ undefined-behavior language-lawyer c++11 c++14
正如初始化所述,需要进行左值到右值的转换?是int x = x;
UB吗?C++标准在3.3.2
声明部分中有一个令人惊讶的例子,其中a int
用它自己的不确定值初始化:
Run Code Online (Sandbox Code Playgroud)int x = 12; { int x = x; }
这里第二个x用它自己的(不确定的)值初始化.- 结束例子 ]
Johannes对此问题的回答表明是未定义的行为,因为它需要左值到右值的转换.
在最新的C++ 14草案标准中N3936
,可以在此处找到此示例已更改为:
Run Code Online (Sandbox Code Playgroud)unsigned char x = 12; { unsigned char x = x; }
这里第二个x用它自己的(不确定的)值初始化.- 结束例子 ]
C++ 14中有关于不确定值和未定义行为的变化,这些变化在示例中引发了这种变化吗?
Sha*_*our 54
是的,这种变化是由语言的变化驱动的,如果评估产生不确定的值,但是对于无符号的窄字符有一些例外,它会使其成为未定义的行为.
可在N3914 1中找到的缺陷报告1787 最近在2014年被接受并纳入最新的工作草案N3936
:
关于不确定值的最有趣的变化将是8.5
第12段,该段来自:
如果没有为对象指定初始化程序,则默认初始化该对象; 如果未执行初始化,则具有自动或动态存储持续时间的对象具有不确定的值.[ 注意:具有静态或线程存储持续时间的对象是零初始化的,请参见3.6.2.- 结束说明 ]
(强调我的):
如果没有为对象指定初始化程序,则默认初始化该对象.当获得具有自动或动态存储持续时间的对象的存储时,该对象具有不确定的值,并且如果没有对该对象执行初始化,则该对象保留不确定的值,直到替换该值为止(5.17 [expr.ass]) .[注意:具有静态或线程存储持续时间的对象是零初始化的,请参见3.6.2 [basic.start.init].-end note] 如果评估产生不确定的值,则行为是未定义的,除非在以下情况中:
如果通过以下评估产生无符号窄字符类型(3.9.1 [basic.fundamental])的不确定值:
条件表达式的第二个或第三个操作数(5.16 [expr.cond]),
逗号的右操作数(5.18 [expr.comma]),
转换或转换为无符号窄字符类型的操作数(4.7 [conv.integral],5.2.3 [expr.type.conv],5.2.9 [expr.static.cast],5.4 [expr.cast]) , 要么
丢弃值表达式(第5条[expr]),
那么操作的结果就是一个不确定的值.
如果通过评估一个简单赋值运算符(5.17 [expr.ass])的右操作数产生无符号窄字符类型(3.9.1 [basic.fundamental])的不确定值,该操作数的第一个操作数是无符号窄值的左值字符类型,不确定值替换左操作数引用的对象的值.
如果在初始化无符号窄字符类型的对象时通过初始化表达式的求值产生无符号窄字符类型(3.9.1 [basic.fundamental])的不确定值,则该对象被初始化为不确定的值.
并包括以下示例:
[ 例如:
Run Code Online (Sandbox Code Playgroud)int f(bool b) { unsigned char c; unsigned char d = c; // OK, d has an indeterminate value int e = d; // undefined behavior return b ? d : 0; // undefined behavior if b is true }
- 结束例子 ]
我们可以在N3936中找到这个文本,这是当前的工作草案,并且N3937
是C++14 DIS
.
在C++之前1y
有趣的是,在这个草案之前,不像C 一直有一个明确指出的使用不确定值的概念是未定义的 C++使用术语不确定值,甚至没有定义它(假设我们不能从C99借用定义)而且见缺陷报告616.我们不得不依赖于低于指定的左值到右值的转换,在草案C++ 11标准中,4.1
Lvalue-to-rvalue转换段落1中有这样的说法:
[...]如果对象未初始化,则需要进行此转换的程序具有未定义的行为.[...]
脚注:
归档时间: |
|
查看次数: |
3991 次 |
最近记录: |