我对这个C ++构造函数感到困惑

时间:2015-01-24 16:15:48

标签: c++ constructor

我尝试寻找答案,但不确定用于描述此问题的最佳术语......

我正在阅读一本关于SFML编程的书,其中一个例子让我对构造函数的用法感到困惑。

假设我们有A类和B类.A类有一个B类成员变量(memberB)。 A的构造函数如下:

A::A() : OtherMemberType(with, params), memberB()
{...}

鉴于使用初始化列表中的默认构造函数初始化了memberB,在列表中明确列出它的目的是什么?如果不将其列入清单,会不会产生同样的效果?

由于

编辑:谢谢你的回答。我现在已经学会了值初始化与默认初始化的(基本)区别。

对于更多上下文,由于“B类可能被破坏”的想法被提出来了,这里是文本SFML Game Development中的代码示例:

class Game
{
    public:Game();
        void             run();

    private:
        void             processEvents();
        void             update();
        void             render();

    private:
        sf::RenderWindow mWindow;
        sf::CircleShape  mPlayer;
};

Game::Game()
: mWindow(sf::VideoMode(640, 480), "SFML Application")
, mPlayer()
{
    mPlayer.setRadius(40.f);
    mPlayer.setPosition(100.f, 100.f);
    mPlayer.setFillColor(sf::Color::Cyan);
}

所以在这种情况下,有没有人知道SFML的一些细节?是sf :: CircleShape“已损坏”,还是对默认构造函数的冗余调用?

亚当

3 个答案:

答案 0 :(得分:16)

初始化初始化列表value-initializes中的成员。从列表中default-initializes省略它,

如果B是非聚合且具有默认构造函数,则没有区别。

如果B是聚合,则可能存在差异。 默认初始化表示如果它包含内置函数,则可能无法初始化。 value-initializing 它最终会产生零初始化其成员的效果。

这是一个初始化语义不同的例子:

struct B
{
  int i, j, k;
};

struct A
{
  A() : b() {} // value-initializes b: b.i, b.j, b.k zero initialized

  B b;
};

struct AA
{
  AA() {} // default-initializes b: b.i, b.j, b.k have no initialization

  B b;
};

答案 1 :(得分:14)

通过将其包含在初始化列表中,该成员是值初始化。如果不是,它将是默认初始化。是否存在差异取决于类型。

如果它是具有声明的默认构造函数的类类型,则没有区别:在任何一种情况下都将使用该构造函数。

否则,值初始化将初始化原始类型(和类类型的原始成员),而在某些情况下,默认初始化将使它们保持未初始化,具有不确定的值。

UPDATE:在您的特定情况下,该类确实有default constructor,因此显式初始化是多余的。但冗余不一定是坏事 - 它表明它是故意进行价值初始化,而不仅仅是被遗忘。

答案 2 :(得分:2)

考虑到迈克和胡安所说的话,我会说,如果需要像那样进行值初始化,那么B类的实现就会被破坏,除非它是合理的期望这样做。

通常,给定一个设计合理的类 - 使用用户提供的默认构造函数iff如果有POD成员 - 在value-和default-初始化类型B的成员之间的行为应该没有区别。

某些特殊类可能无法对其成员执行零初始化,并且可能缺少默认构造函数。 std::array就是这样一个类。他们试图保留其实现的原始类型的性能。这些类的成员将需要值初始化。

有几种可能性:

  1. B具有通常的行为,值初始化是多余的。具体做法是:

    a)类B没有POD类型的成员,非POD类型的成员类型都是按照可能性#1或

    实现的

    b)类B的用户编写的默认构造函数会根据需要初始化所有POD类型的成员。

  2. B具有性能优化类型的语义,例如数字类型或原始C数组的替代。它缺少默认构造函数,除非您执行值初始化,否则不会初始化。示例:std::array<T>其中T是POD。

  3. B是模板参数。在B没有任何约束的情况下,值初始化是唯一安全的选择。毕竟,B可能是std::array

  4. 班级B已被破坏。如果其实例的值已初始化,则其成员将被正确初始化。它需要修复。