【发布时间】:2020-03-05 05:58:50
【问题描述】:
我知道这里有很多关于此主题的已回答问题,但我找不到完全回答我的问题的问题。
下面我根据我对初始化的理解(从 C++17 开始)做出一些假设。如果有人能指出/纠正我的错误,那就太好了。
给定类型
struct A
{
int x;
};
创建局部变量根本不会初始化对象
A a; // a.x is indeterminate, accessing it is UB
但是,我们可以通过以下方式强制聚合初始化
A a{};
A a = {};
将a.x 初始化为0。
现在,给定类型
struct B
{
int x;
std::string s;
};
创建局部变量默认初始化对象
B b;
这导致b.s被默认初始化(因为它是一个非POD)但b.x是不确定的,访问它仍然是UB。
接下来,我们有
struct C
{
int x = 0;
std::string s;
};
创建局部变量默认初始化对象
C c;
这导致 C.s 被默认初始化(因为它是一个非 POD)和 c.x 被复制初始化,行为是明确定义的。
最后,让我们比较一些类型并检查它们是否具有相同的初始化行为。我假设如果我创建一个(默认初始化的)局部变量(A a;),这些类型之间没有区别。
案例A
struct A1
{
int x;
};
struct A2
{
A2() { }
int x;
};
struct A3
{
A3() = default;
int x;
};
x 从未初始化,它的值是不确定的。
案例 B
struct B1
{
int x{};
};
struct B2
{
B2() : x{} { }
int x;
};
struct B3
{
B3() = default;
int x = 0;
};
x 总是被初始化,它的值是0。
案例 C
struct C1
{
int x;
std::string s;
};
struct C2
{
C2() { }
int x;
std::string s;
};
struct C3
{
C3() = default;
int x;
std::string s;
};
s 总是默认初始化,但x 从不初始化,它的值是不确定的。
这些陈述是否正确,如果不正确,错误在哪里,实际行为是什么?
【问题讨论】:
-
你的假设是正确的。
-
经验法则:如果类型有构造函数,则不需要任何工作,构造函数会做。如果没有,则不会为您做任何事情,您要么指定一个值,要么得到一个不确定的值。
-
@NathanOliver-ReinstateMonica “如果该类型有构造函数,则不需要工作” 这不是与案例 C 相矛盾吗?这是否意味着 POD 根本没有构造函数(甚至没有隐式生成的构造函数)?
-
这与案例 C 不矛盾 是的,但 on 可能会争辩说
C有一个有缺陷的构造函数,因为它没有做“正确的事情”。 POD 确实有一个不执行任何操作的隐式生成的构造函数。这就是为什么它是一个经验法则,而不是“法律”。 POD 是一个例外,因为它们是一个类,但我们希望将它们视为原语。 -
@Timo:什么是 POD?在您将
std::string放入其中的那一刻,它就不再是 POD。您似乎在谈论聚合。
标签: c++ initialization language-lawyer c++17