垃圾的C ++对象构造,为什么?

时间:2016-02-17 06:22:05

标签: c++ c++11

我有以下结构:

struct MyStruct
{
    struct Displacement
    {
        bool            isWrapped;
        int             steps;
    };

    int                     initialDuration;
    int                     currentDuration;
    Displacement            displacement1;
    Displacement            displacement2;
};

我正在使用它:

MyStruct obj{2, 2};
auto shared = std::make_shared<MyStruct>(obj);

问题是我需要将前两个参数复制为initialDuration,而currentDuration在创建新对象时应该相同。因此我创建了一个CTOR:

struct MyStruct
{
    struct Displacement
    {
        bool            isWrapped;
        int             steps;
    };

    MyStruct(int duration) 
          : initialDuration(duration)
          , currentDuration(duration)
    {
    }

    int                     initialDuration;
    int                     currentDuration;
    Displacement            displacement1;
    Displacement            displacement2;
};

然后像这样使用:

    auto shared = std::make_shared<MyStruct>(2);

意外的事情1是: Displacement的{​​{1}}成员都已使用垃圾进行初始化。对于MyStruct的{​​{1}}成员,对于另一个成员 - booltrue s是一些任意数字。

所以我可能也需要为false定义CTOR。定义如下:

int

意想不到的事情2是:,在其他地方

Displacement

开始无法编译。在定义默认CTOR时,我不知道aggregate initializationlist-initialization已停止为POD结构工作。

请解释这两种行为的原因。

3 个答案:

答案 0 :(得分:2)

如果您有一个被调用的构造函数,则需要显式初始化所有成员,否则它们将被取消初始化。未初始化的成员将具有不确定值,这是您认为的垃圾。当你有构造函数时,这就是C ++的工作方式。

来自this implicit default constructor reference

  

如果隐式声明的默认构造函数未定义为已删除,则由编译器定义...它与具有空主体和空初始化列表的用户定义构造函数具有完全相同的效果。也就是说,它调用base的默认构造函数和此类的非静态成员。

内置或聚合类型没有构造函数,因此无需显式初始化即可构造或初始化。

答案 1 :(得分:2)

第一个问题

  

MyStruct的两个Displacement成员都已用垃圾初始化。

     

(来自评论)应该有一个由编译器定义的Displacement的默认CTOR,它应该在我定义的MyStruct的CTOR中调用,对吗?

implicitly-defined default constructor在这里做了什么。

  

如果隐式声明的默认构造函数未定义为已删除,则由编译器定义(即,生成并编译函数体),它与用户定义的构造函数具有完全相同的效果正文和空初始化列表。也就是说,它调用base的默认构造函数和此类的非静态成员。

对于MyStruct obj{2, 2};obj是一个自动对象,所以(来自标准的$ 8.5 / 12初始值设定项[dcl.init])

  

如果没有为对象指定初始值设定项,则默认初始化该对象。存储对象时   获得自动或动态存储持续时间,该对象具有不确定值,如果   没有对该对象执行初始化,该对象保留一个不确定的值,直到该值为止   替换(5.18)。 [注意:具有静态或线程存储持续时间的对象是零初始化的,请参见3.6.2。 -   结束说明]

您可能希望将它们初始化为

MyStruct obj{2, 2, {false, 0}, {false, 0}};

第二个问题

  

当我定义默认的CTOR时,我不知道聚合初始化或列表初始化停止为POD结构工作。

是的,除非您提供另一个以std::initializer_list为参数的ctor。见aggregate initialization

  

聚合是一种类型的对象,它是以下之一

array type  
class type (typically, struct or union), that has  
    no private or protected non-static data members
    no user-provided constructors (explicitly defaulted or deleted constructors are allowed) (since C++11)
    no base classes
    no virtual member functions 
    no default member initializers (since C++11) (until C++14)

答案 2 :(得分:1)

添加默认构造函数时,您的结构不再是POD type。除此之外,POD类型必须具有trivial default constructor

您需要添加一个构造函数,该构造函数为您的代码提供两个参数以便再次开始工作。另请注意,默认构造函数不会初始化成员。它之前使用POD类型的原因是进行聚合初始化(仅适用于POD类型)默认成员未明确初始化为0.