默认构造函数初始化

时间:2012-02-18 11:23:21

标签: c++

考虑以下代码:

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;
}

当我更改它时,该程序提供不同的输出:

  1. 如果我注释掉First ob;行,则x的值初始化为零
  2. 如果类包含First类的对象,则member具有垃圾值。
  3. 如果我创建像Second obj;这样的对象,那么它就有垃圾值。
  4. 当第二类只包含内置成员和另一个类的对象时,它的行为有何不同?

    这些陈述之间有什么区别:

    Second obj = Second();
    Second obj;
    

3 个答案:

答案 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,而不会影响此示例。