在自己的初始化器中使用变量
Use of variable in own initializer
[basic.scope.pdecl]/1 of the C++20 standard draft had the following (non-normative) example in a note (partial quote from before the merge of pull request 3580,请参阅此问题的答案):
unsigned char x = x;
[...] x is initialized with its own (indeterminate) value.
这实际上在 C++20 中具有明确定义的行为吗?
通常,T x = x;
形式的自初始化具有未定义的行为,因为 x
的值在初始化完成之前是 不确定的。评估不确定值通常会导致未定义的行为([basic.indent]/2), but there is a specific exception in [basic.indent]/2.3 允许从具有不确定值的左值 unsigned char
直接初始化 unsigned char
变量(导致使用不确定值进行初始化)。
因此,这本身不会导致未定义的行为,但对于其他类型 T
不是无符号窄字符类型或 std::byte
,例如int x = x;
。这些注意事项也适用于 C++17 及之前的版本,另请参阅底部的链接问题。
但是,即使对于 unsigned char x = x;
,当前草案的 [basic.lifetime]/7 表示:
Similarly, before the lifetime of an object has started [...] using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if:
the glvalue is used to access the object, or
[...]
这似乎暗示示例中 x
的值只能在其生命周期内使用。
[...]
The lifetime of an object of type T begins when:
- [...] and
- its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),
[...]
因此x
的生命周期只有在初始化完成后才开始。但在引用的示例中,x
的值在 x
的初始化完成之前使用。因此,使用具有未定义的行为。
我的分析是否正确?如果正确,是否会影响初始化前使用的类似情况,例如
int x = (x = 1);
据我所知,哪些在 C++17 及之前的版本中也有明确定义?
请注意,在 C++17(最终草案)中,生命周期开始的第二个要求是 different:
- if the object has non-vacuous initialization, its initialization is complete,
由于 x
根据 C++17 的定义(但不是当前草案中的定义)会进行空洞的初始化,因此当在上面给出的示例中的初始化程序中访问它时,它的生命周期就已经开始了因此在这两个示例中,由于 C++17 中 x
的生命周期,没有未定义的行为。
C++17之前的写法又不一样了,结果一样
问题不在于使用不确定值时的未定义行为,这在例如以下问题:
- Has C++ standard changed with respect to the use of indeterminate values and undefined behavior in C++14?
- Does initialization entail lvalue-to-rvalue conversion? Is
int x = x;
UB?
这是作为 editorial issue. It was forwarded to CWG for (internal) discussion. Approximately 24 hours later, the person who forwarded the issue created a pull request 打开的,它修改了示例以明确这是 UB:
Here, the initialization of the second \tcode{x} has undefined behavior, because the initializer accesses the second \tcode{x} outside its lifetime\iref{basic.life}.
该 PR 已添加,问题已关闭。因此,显而易见的解释(由于访问生命周期尚未开始的对象而导致的 UB)似乎很明显是预期的解释。委员会 的意图似乎是 使这些结构失效,并且已更新标准的非规范性文本以反映这一点。
[basic.scope.pdecl]/1 of the C++20 standard draft had the following (non-normative) example in a note (partial quote from before the merge of pull request 3580,请参阅此问题的答案):
unsigned char x = x;
[...] x is initialized with its own (indeterminate) value.
这实际上在 C++20 中具有明确定义的行为吗?
通常,T x = x;
形式的自初始化具有未定义的行为,因为 x
的值在初始化完成之前是 不确定的。评估不确定值通常会导致未定义的行为([basic.indent]/2), but there is a specific exception in [basic.indent]/2.3 允许从具有不确定值的左值 unsigned char
直接初始化 unsigned char
变量(导致使用不确定值进行初始化)。
因此,这本身不会导致未定义的行为,但对于其他类型 T
不是无符号窄字符类型或 std::byte
,例如int x = x;
。这些注意事项也适用于 C++17 及之前的版本,另请参阅底部的链接问题。
但是,即使对于 unsigned char x = x;
,当前草案的 [basic.lifetime]/7 表示:
Similarly, before the lifetime of an object has started [...] using the properties of the glvalue that do not depend on its value is well-defined. The program has undefined behavior if:
the glvalue is used to access the object, or
[...]
这似乎暗示示例中 x
的值只能在其生命周期内使用。
[...]
The lifetime of an object of type T begins when:
- [...] and
- its initialization (if any) is complete (including vacuous initialization) ([dcl.init]),
[...]
因此x
的生命周期只有在初始化完成后才开始。但在引用的示例中,x
的值在 x
的初始化完成之前使用。因此,使用具有未定义的行为。
我的分析是否正确?如果正确,是否会影响初始化前使用的类似情况,例如
int x = (x = 1);
据我所知,哪些在 C++17 及之前的版本中也有明确定义?
请注意,在 C++17(最终草案)中,生命周期开始的第二个要求是 different:
- if the object has non-vacuous initialization, its initialization is complete,
由于 x
根据 C++17 的定义(但不是当前草案中的定义)会进行空洞的初始化,因此当在上面给出的示例中的初始化程序中访问它时,它的生命周期就已经开始了因此在这两个示例中,由于 C++17 中 x
的生命周期,没有未定义的行为。
C++17之前的写法又不一样了,结果一样
问题不在于使用不确定值时的未定义行为,这在例如以下问题:
- Has C++ standard changed with respect to the use of indeterminate values and undefined behavior in C++14?
- Does initialization entail lvalue-to-rvalue conversion? Is
int x = x;
UB?
这是作为 editorial issue. It was forwarded to CWG for (internal) discussion. Approximately 24 hours later, the person who forwarded the issue created a pull request 打开的,它修改了示例以明确这是 UB:
Here, the initialization of the second \tcode{x} has undefined behavior, because the initializer accesses the second \tcode{x} outside its lifetime\iref{basic.life}.
该 PR 已添加,问题已关闭。因此,显而易见的解释(由于访问生命周期尚未开始的对象而导致的 UB)似乎很明显是预期的解释。委员会 的意图似乎是 使这些结构失效,并且已更新标准的非规范性文本以反映这一点。