考虑以下代码片段:
class A
{
public:
A(int a, int b) : j(a), i(j + b) {}
int i, j;
};
int main()
{
A a(10, 20);
std::cout << a.i << " " << a.j << std::endl;
return 0;
}
标准says,成员变量的初始化顺序是声明它们的顺序。在这种情况下,i
将在j
之前初始化。由于j
尚未初始化,请先i = *a garbage value* + 20
,然后再用j
初始化10
。
代码prints 20 10
。
即,j
在计算0
时被认为是i
。
在这种情况下,标准保证是否对内置类型使用默认值?还是仅仅是垃圾值恰好是0
?还是未定义的行为?
答案 0 :(得分:1)
j + b
是未定义的行为,因为它在允许这样做的特定实例之一之外使用了不确定的值(j
在初始化之前的值)(所有这些都与{{ 1}}变体,而char
(而不是std::byte
,则是不确定的值)。
在C ++ 20中,它也将具有未定义的行为,因为您正在访问int
之外的时间。根据我在C ++ 17中的了解,j
的生存期始于其存储的分配,因为j
的初始化是 vacuous 。但是,在C ++ 20中,空虚初始化和生存期的定义会发生变化。
因此无论如何在初始化之前使用变量都是非常不明智的选择。
答案 1 :(得分:1)
在这种情况下,标准保证对内置类型使用默认值吗?
不。在这种情况下,该值是不确定的。
还是未定义的行为?
是的。读取不确定值的行为是不确定的(窄字符类型IIRC除外)。