C++ 基元类型的类成员的初始化行为

C++ 基元类型的类成员的初始化行为,c++,initialization,language-lawyer,c++17,C++,Initialization,Language Lawyer,C++17,我知道这里有很多关于这个话题的回答问题,但我找不到一个完全回答我问题的 下面,我将根据自己对初始化的理解(从C++17开始)做出一些假设。如果有人能指出/纠正我的错误就好了 给定类型 struct A { int x; }; struct B { int x; std::string s; }; 创建局部变量根本不会初始化对象 A a; // a.x is indeterminate, accessing it is UB 但是,我们可以通过以下方式强制执行聚

我知道这里有很多关于这个话题的回答问题,但我找不到一个完全回答我问题的

下面,我将根据自己对初始化的理解(从C++17开始)做出一些假设。如果有人能指出/纠正我的错误就好了

给定类型

struct A
{
    int x;  
};
struct B
{
    int x;
    std::string s;
};
创建局部变量根本不会初始化对象

A a;  // a.x is indeterminate, accessing it is UB
但是,我们可以通过以下方式强制执行聚合初始化

A a{};
A a = {};
它将
a.x
初始化为
0

现在,考虑到类型

struct A
{
    int x;  
};
struct B
{
    int x;
    std::string s;
};
创建局部变量默认值将初始化对象

B b;
C c;
这导致
b.s
默认初始化(因为它是非POD),但
b.x
不确定,访问它仍然是UB

接下来,我们有

struct C
{
    int x = 0;
    std::string s;
};
创建局部变量默认值将初始化对象

B b;
C c;
这导致
C.s
被默认初始化(因为它是非POD)和
C.x
被复制初始化,行为定义良好

最后,让我们比较一些类型并检查它们是否具有相同的初始化行为。如果我创建一个(默认初始化的)局部变量(
a;
),我假设这些类型之间没有区别

案例A
x
从未初始化,其值不确定

案例B
x
始终初始化,其值为
0

案例C
s
始终默认初始化,但
x
从未初始化,其值不确定


这些陈述是否正确?如果不正确,错误在哪里?实际行为是什么?

您只遗漏了一个细微之处:对于
A3
C3
,编写
t3t{}
T3()
初始化
x
为0,因为在其第一次声明中默认的默认构造函数会导致值初始化为零,从而初始化对象。

您的假设是正确的。经验法则:如果类型具有构造函数,则不需要执行任何操作,则构造函数会执行此操作。如果没有,将不会为您做任何事情,您要么指定一个值,要么得到一个不确定的值。@NathanOliver,“如果类型有构造函数,则不需要任何工作”,这与案例C不矛盾吗?这是否意味着POD根本没有构造函数(甚至没有隐式生成的构造函数)?这是否与案例C相矛盾?是的,但on可能会争辩说
C
有一个有缺陷的构造函数,因为它没有做“正确的事情”。POD确实有一个隐式生成的构造函数,它什么也不做。这就是为什么这是一条经验法则,而不是“法律”。POD是一个例外,因为它们是一个类,但我们想把它们当作一个原语。@Timo:什么是POD?当你把一个
std::string
放进去的那一刻,它就不再是一个豆荚了。你似乎在谈论聚合。是的,我并没有故意提到零初始化,因为显式使用了括号或大括号。因为通常情况下,人们不会编写
std::string s{}
std::vec{}而不是
std::string s
std::vec。蒂莫:对于你的第一个
A
,你提到了这两种语法,还有
vector::resize
do值初始化,所以我认为这是相关的。