问题描述
如初始化是否需要左值右值转换?是 int x = x;
UB 吗? C++ 标准在 3.3.2
声明点 部分有一个令人惊讶的例子,其中int
用它自己的不确定值初始化:
int x = 12;{ int x = x;}
这里第二个 x 用它自己的(不确定的)值初始化.— 结束示例 ]
Johannes 对这个问题的回答表明是未定义的行为,因为它需要左值到右值的转换.
在最新的 C++14 草案标准 N3936
中可以找到 此处 此示例已更改为:
unsigned char x = 12;{ 无符号字符 x = x;}
这里第二个 x 用它自己的(不确定的)值初始化.— 结束示例 ]
C++14 中关于不确定值和未定义行为的某些变化是否导致了示例中的这种变化?
是的,这个变化是由语言的变化驱动的,这使得它的行为不确定如果一个不确定的值是由评估产生的但是除了无符号窄字符的一些例外.
缺陷报告 1787文本可以在 N3914 中找到 是 最近于 2014 年接受并纳入最新的工作草案N3936
:
关于不确定值的最有趣的变化是 8.5
段 12 来自:
如果没有为对象指定初始化器,则对象默认初始化;如果不进行初始化,具有自动或动态存储期限的对象具有不确定的值.[ 注意: 具有静态或线程存储期的对象是零初始化的,参见 3.6.2.— 尾注 ]
到(强调我的):
如果没有为对象指定初始化器,则该对象是默认初始化.当存储具有自动或获取动态存储时长,对象有一个不确定值,如果没有对对象进行初始化,那对象保留一个不确定的值,直到该值被替换(5.17 [expr.ass]).[注意:具有静态或线程存储的对象持续时间是零初始化的,参见 3.6.2 [basic.start.init].-结尾注意] 如果评估产生不确定的值,则除以下情况外,行为未定义:
如果无符号窄字符类型 (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]),
那么运算的结果是一个不确定的值.
如果一个无符号窄字符类型(3.9.1 [basic.fundamental])的不确定值是由右一个简单赋值运算符 (5.17 [expr.ass]) 的操作数,其第一个操作数是一个无符号窄字符类型的左值,一个不确定值替换引用的对象的值左操作数.
如果无符号窄字符类型 (3.9.1 [basic.fundamental]) 的不确定值是通过对初始化无符号对象时的初始化表达式窄字符类型,该对象被初始化为不确定的价值.
并包含以下示例:
[ 示例:
int f(bool b) {无符号字符 c;无符号字符 d = c;//好的,d 有一个不确定的值内部 e = d;//未定义的行为返回 b ?d:0;//如果 b 为真,则未定义行为}
— 结束示例 ]
我们可以在 N3936 中找到此文本,这是当前的 工作草案和N3937
是 C++14 DIS
.
在 C++1y 之前
有趣的是,在这个草案之前,不同于 C 一直对不确定值的用途有明确的定义 C++ 使用术语不确定值甚至没有定义它(假设我们不能从 C99 借用定义) 以及参见缺陷报告 616.我们不得不依赖 未指定的左值到右值转换,在 C++11 标准草案在4.1
左值到右值转换段落1中有介绍,它说:
[...]如果对象未初始化,则需要进行此转换的程序具有未定义的行为.[...]
脚注:
As covered in Does initialization entail lvalue-to-rvalue conversion? Is int x = x;
UB? the C++ standard has a surprising example in section 3.3.2
Point of declaration in which an int
is initialized with it's own indeterminate value:
Which Johannes answer to this question indicates is undefined behavior since it requires an lvalue-to-rvalue conversion.
In the latest C++14 draft standard N3936
which can be found here this example has changed to:
Has something changed in C++14 with respect to indeterminate values and undefined behavior that has driven this change in the example?
Yes, this change was driven by changes in the language which makes it undefined behavior if an indeterminate value is produced by an evaluation but with some exceptions for unsigned narrow characters.
Defect report 1787 whose proposed text can be found in N3914 was recently accepted in 2014 and is incorporated in the latest working draft N3936
:
The most interesting change with respect to indeterminate values would be to section 8.5
paragraph 12 which goes from:
to (emphasis mine):
and included the following example:
We can find this text in N3936 which is the current working draft and N3937
is the C++14 DIS
.
Prior to C++1y
It is interesting to note that prior to this draft unlike C which has always had a well specified notion of what uses of indeterminate values were undefined C++ used the term indeterminate value without even defining it (assuming we can not borrow definition from C99) and also see defect report 616. We had to rely on the underspecified lvalue-to-rvalue conversion which in draft C++11 standard is covered in section 4.1
Lvalue-to-rvalue conversion paragraph 1 which says:
Footnotes:
1787
is a revision of defect report 616, we can find that information in N3903
这篇关于C++ 标准是否在 C++14 中关于不确定值和未定义行为的使用发生了变化?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!