当前位置: 首页 > 知识库问答 >
问题:

嵌套类的值初始化

海新霁
2023-03-14

根据价值初始化规则。发生值初始化:

1,5)当使用由空括号或大括号组成的初始值设定项创建无名临时对象时(从C 11开始);

2,6)当一个具有动态存储持续时间的对象是由一个新表达式创建的,初始化器由一对空括号或大括号组成(从C11开始);

3,7)当使用带有空括号或大括号对的成员初始值设定项初始化非静态数据成员或基类时(自C 11起);

4)当使用由一对大括号组成的初始化程序声明命名变量(自动、静态或线程本地)时。

微不足道的例子

struct A{
    int i;
    string s;
    A(){};
};

A a{} 
cout << a.i << endl // default initialized value

没有显式声明的构造函数并留下默认的默认ctor//编译器生成的一个我们得到的。

struct A{
    int i;
    string s;

};
A a{};
cout << a.i << endl // zero-initialized value

然而,使用antoher结构。

struct A{
    int i;
    string s;

};

struct B{
    A a;
    int c;
};

B a{};
cout << a.a.i << endl // default initialized , even tho we did not , int struct B , declared A a{}.

即使没有使用{}/()构造,a.i的值也是零初始化的,这违反了规则(如果我没有弄错的话)。

在结构B上使用相同的逻辑

struct A{
    int i;
    string s;

};

struct B{
    A a;
    int c;
};

B b;
cout << b.c << endl; // default inicialized

我们按照规则行事。

最后一个例子:

struct A
{
    int i;
    A() { } 
};

struct B { A a; }; 

std::cout << B().a.i << endl;

B(). a. i也是零初始化的,而我们显式声明了构造函数并且没有删除它。

为什么这些值初始化为零?根据这里所述的规则,它们应该是默认初始化的,而不是零初始化的。

谢谢你的回答。

共有2个答案

那存
2023-03-14

根据聚合初始化规则,成员确实是值初始化的。

值初始化:

在所有情况下,如果使用空括号对{},并且T是聚合类型,则执行聚合初始化,而不是值初始化。

聚合初始化的影响包括:

郜驰
2023-03-14

这是A是否是聚合的区别。

[dcl.init.aggr](强调)

聚合是一个数组或类(第9条),没有用户提供的构造函数(12.1),没有用于非静态数据成员的大括号或等效初始值设定项(9.2),没有私有或受保护的非静态数据成员(第11条),

因此,当A没有声明的构造函数时,说A{}具有聚合初始化的效果

这将使用空初始化列表构造每个成员:

如果列表中的初始化子句少于集合中的成员,则每个未显式初始化的成员都应从空初始化子句列表中初始化

因此得到int{}和std::string{},这将值初始化整数成员为零。

如果确实提供了默认构造函数,则aggregate属性将丢失,并且int成员保持未初始化状态,因此访问它被视为未定义行为。

具体来说:

在访问a.i时,此代码是未定义的行为,因为您提供了一个用户定义的构造函数,因此在构造后,int i字段保持未初始化状态:

struct A{
    int i;
    string s;
    A(){};
};

A a{} ;
cout << a.i << endl;

当访问b.c时,此代码表现出未定义的行为,因为您没有在b上执行列表初始化:

struct B{
    A a;
    int c;
};

B b;
cout << b.c << endl;

所有其他代码都可以,并且将零初始化整数字段。在您使用大括号{}的场景中,您正在执行聚合初始化。

最后一个例子有点棘手,因为您正在执行值初始化。由于B是一个集合,它得到零初始化([dcl.init]),其中:

每个基类子对象初始化为零

同样,您可以访问子对象的整数成员。

 类似资料:
  • 问题内容: 我不知道如何初始化嵌套结构。在此处找到示例:http: //play.golang.org/p/NL6VXdHrjh 问题答案: 好吧,有什么特定的原因不使Proxy成为自己的结构? 无论如何,您有2个选择: 正确的方法是,只需将proxy移至其自己的结构,例如: 不太正确和丑陋的方法,但仍然有效:

  • 问题内容: 我有一个json作为 我想将我的结构编组到json之上并创建如下结构- 我在初始化上述结构时遇到麻烦。我不确定如何以以下方式初始化匿名结构: 我通过为页面信息创建一个单独的结构并将其与父结构附加在一起来解决此问题。但是,必须有某种方法来执行 匿名 嵌套结构的初始化,就像我对上面的 Fields (字符串切片)所做的一样。谁能将我重定向到一些指南来做到这一点? 问题答案: 这可行,但是很

  • 问题内容: 您如何初始化以下结构? 我试过了: 没用: 我试过了: 没用: 问题答案: 您是一个具有匿名结构类型的字段。因此,您必须重复类型定义: 但在大多数情况下,最好将其定义为rob74建议的单独类型。

  • 问题内容: 我怎样才能做到这一点: … 给出的编译结果为:“结构文字中的未知B字段’MemberA’” 当提供像这样的文字结构成员值时,如何初始化MemberA(从“父”结构)? 问题答案: 初始化时,匿名结构仅在其类型名称下(在您的情况下)是已知的。与该结构关联的成员和函数仅在实例存在之后才导出到外部。 您必须提供一个有效的实例来初始化: 编译错误 结构文字中的未知B字段’MemberA’ 确切

  • 问题内容: 嗨,我是Golang的新手,请帮助我。我已经在结构内部定义了一个结构。但是,当我尝试初始化主结构时出现错误。 我得到的错误是:不能在字段值中使用(类型接口{})作为类型结构:需要类型声明。 请提出一种初始化DetailsFilter的方法。我尝试执行在Golang中初始化嵌套结构中描述的方法,但即使这样也不起作用。 问题答案: 不幸的是,如果结构字段的类型是匿名结构,则 _在构造时_只

  • 请考虑以下示例: 如果我理解正确的话,根据https://en.cppreference.com/w/cpp/language/zero_initialization,它不能抛出,因为应该对B::A执行零初始化,就像对“没有构造函数的值初始化类类型的成员”一样。 如果它抛出,是编译器错误还是我遗漏了什么? 编辑:我在英特尔网站上提交了一个bug:https://community.intel.co