gpt4 book ai didi

c++ - 嵌套类的值初始化

转载 作者:行者123 更新时间:2023-11-28 01:41:10 25 4
gpt4 key购买 nike

按值初始化规则。值初始化发生:

1,5) when a nameless temporary object is created with the initializer consisting of an empty pair of parentheses or braces (since C++11);

2,6) when an object with dynamic storage duration is created by a new-expression with the initializer consisting of an empty pair of parentheses or braces (since C++11);

3,7) when a non-static data member or a base class is initialized using a member initializer with an empty pair of parentheses or braces (since C++11);

4) when a named variable (automatic, static, or thread-local) is declared with the initializer consisting of a pair of braces.

简单的例子

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

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

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

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 也被零初始化,而我们显式声明了构造函数并且它没有被删除。

为什么这些值初始化为零?按规定here它们应该默认初始化而不是零初始化。

感谢您的回答。

最佳答案

这就是A是聚合还是非聚合的区别。

[dcl.init.aggr](强调我的)

An aggregate is an array or a class (Clause 9) with no user-provided constructors (12.1), no brace-or-equal initializers for non-static data members (9.2), no private or protected non-static data members (Clause 11),

所以当 A 没有声明的构造函数时,说 A a{} 的效果是 aggregate initialization

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

If there are fewer initializer-clauses in the list than there are members in the aggregate, then each member not explicitly initialized shall be initialized from an empty initializer list

因此您得到 int{}std::string{},它们会将整数成员值初始化为零。

当您提供默认构造函数时,聚合属性会丢失并且 int 成员保持未初始化状态,因此访问它被视为未定义行为。


具体来说:

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

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

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

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

struct B{
A a;
int c;
};

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

所有其他代码都没有问题,并将对整数字段进行零初始化。在您使用大括号 {} 的情况下,您正在执行聚合初始化

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

each base-class subobject is zero-initialized

因此,您再次可以访问 A 子对象的整数成员。

关于c++ - 嵌套类的值初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47096920/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com