考虑以下代码:
class First
{
public:
int y;
First()
{
y = 90;
}
};
class Second{
public:
int x;
First ob; //if i comment it, value of x is initialised to zero
};
int main()
{
Second obj = Second();
cout << obj.x << endl;
}
当我更改它时,该程序提供不同的输出:
First ob;
行,则x的值初始化为零Second obj;
这样的对象,那么它就有垃圾值。当第二类只包含内置成员和另一个类的对象时,它的行为有何不同?
这些陈述之间有什么区别:
Second obj = Second();
Second obj;
答案 0 :(得分:3)
案例1.当您注释掉行First ob
时,Second
类成为POD类型,可以使用语法Second obj= Second()
进行值初始化,并进行值初始化,如果是内置类型,则表示零初始化,因此x
为零初始化。
案例2:当你保留行First ob
时,Second
类变为非POD类型,因为First
类是非POD类型(因为它具有用户定义的构造函数) 1 ])。在这种情况下,如果您没有在构造函数中初始化它,则语法Second obj=Second()
不会初始化内置数据类型。
案例3:写Second obj
时,又有两个案例(仔细阅读):
obj
行, First ob
将默认构建。在这种情况下,x
根本不会被初始化,因为它不会在Second
的构造函数中手动初始化。
obj
行被注释掉,则 First ob
根本不会被初始化。在这种情况下,Second
成为POD,如果您只编写Second obj
,则不会初始化POD类型。
1 请参阅此相关主题:
答案 1 :(得分:1)
仔细阅读Do the parentheses after the type name make a difference with new?的已接受答案 - 如果没有First
对象,您的课程就是'A',您的课程就是'B'。 Second obj;
会默认初始化它,Second obj = Second();
会对其进行初始化。
这是C ++有一些非常棘手和令人惊讶的规则的领域之一,但我不打算详细介绍它们,因为它们在上面的问题中得到了很好的解释。
What do the following phrases mean in C++: zero-, default- and value-initialization?也是相关的。
编辑:
上面的链接只是真正涵盖了事物的初始化方面,而不是关于什么使得类琐碎/ POD /标准布局等的规则。 What are Aggregates and PODs and how/why are they special?涵盖了这方面的内容。
答案 2 :(得分:1)
冒着有点切线的风险,让我发布一个问题的修改版本,以及讨论。让我们考虑一下这些类:
struct Agatha
{
int x;
};
struct Claire
{
Claire() { }
int x;
};
为了简化初始化语法并使用Valgrind对示例进行分析,让我们使用动态对象:
#include <memory>
#include <iostream>
int main()
{
std::unique_ptr<Agatha> p1(new Agatha); // #1d
std::unique_ptr<Agatha> p2(new Agatha()); // #1v
std::unique_ptr<Claire> q1(new Claire); // #2d
std::unique_ptr<Claire> q2(new Claire()); // #2v
std::cout << p1->x
<< p2->x
<< q1->x
<< q2->x
<< std::endl;
}
只有一个的打印行是正确的!你能弄明白哪一个吗?
答案是#1v。我们来讨论一下:
案例#1d默认初始化一个聚合,默认初始化每个成员,默认初始化Agatha::x
,使其保持未初始化状态。
案例#1v值初始化一个聚合,它对所有成员进行值初始化,从而对Agatha::x
进行值初始化,从而对其进行零初始化。 (这是个好例子。)
案例#2d默认初始化非聚合,调用默认构造函数。 Claire
的默认构造函数不初始化Claire::x
,因此未初始化。
案例#2d非聚合的值初始化也调用默认构造函数,情况与#2v相同。
请注意,整个讨论与PODness无关,而只是与类是否是聚合类似,如Agatha
,或类似Claire
的非平凡类类型。您可以将std::string
类型的成员添加到Agatha
,而不会影响此示例。