Подтвердить что ты не робот

Я запутался в этом конструкторе С++

Я попытался найти ответ, но не уверен, что наилучшим образом использовать его для описания...

Я читаю книгу о программировании SFML, и один из примеров меня смутил с использованием конструктора.

Допустим, что у нас есть класс A и класс B. Класс A имеет переменную-член типа B (memberB). Конструктор для A выглядит так:

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

Учитывая, что memberB инициализируется конструктором по умолчанию в списке инициализации, какова цель явного перечисления его в списке? Не был бы такой же эффект без включения его в список?

Спасибо

EDIT: Спасибо за ответы. Теперь я узнал (основную) разницу инициализации значения и инициализации по умолчанию.

Для большего контекста, поскольку идея "класс B может быть сломана, была поднята", вот пример кода из текста Разработка игры SFML:

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? Is sf:: CircleShape "сломан", или это избыточный вызов конструктора по умолчанию?

Адам

4b9b3361

Ответ 1

Включив его в список инициализации, элемент инициализируется значением. Если бы это не так, это было бы инициализировано по умолчанию. Существует ли разница в типе.

Если это тип класса с объявленным конструктором по умолчанию, то нет никакой разницы: этот конструктор будет использоваться в любом случае.

В противном случае инициализация значения будет инициализировать нулевые примитивные типы (и примитивные элементы классов), в то время как в некоторых случаях инициализация по умолчанию оставит их неинициализированными с неопределенным значением.

UPDATE: В вашем конкретном случае класс имеет конструктор по умолчанию, поэтому явная инициализация избыточна. Но избыточность не обязательно является плохим - это указывает на то, что она намеренно инициализируется значением, а не просто забывается.

Ответ 2

Инициализация члена в списке инициализаторов значение инициализирует его. Опустив его из списка default-initializes,

Если B является неагрегатом и имеет конструктор по умолчанию, нет никакой разницы.

Если B - совокупность, то может быть разница. инициализация по умолчанию означает, что если он содержит встроенные модули, они не могут быть инициализированы. инициализация значения в конечном итоге приведет к нулевой инициализации его членов.

Это пример, где семантика инициализации будет различной:

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

Ответ 3

Учитывая то, что сказал майк и юань, я бы сказал, что реализация класса B нарушена, если для этого требуется инициализация значений таким образом, если не будет разумно ожидать, что она будет вести себя таким образом.

Как правило, с учетом правильно спроектированного класса - с предоставленным пользователем конструктором по умолчанию iff, если есть члены POD - не должно быть разницы в поведении между инициализацией значения и инициализации по умолчанию членом типа B.

Некоторые специальные классы могут не выполнять нулевую инициализацию своих членов, и у них может отсутствовать конструктор по умолчанию. std::array - один из таких классов. Они пытаются сохранить производительность исходного типа, лежащего в основе их реализации. Для членов таких классов потребуется инициализация значения.

Существует несколько возможностей:

  • Класс B имеет обычное поведение, инициализация значения является излишней. В частности:

    a) класс B не имеет элементов, набранных POD, и типы типизированных типов, отличных от POD, все реализованы в соответствии с возможностью # 1 или

    b) class B пользовательский конструктор по умолчанию инициализирует все элементы, набранные POD, по мере необходимости.

  • Класс B имеет семантику оптимизированного по производительности типа, такого как числовой тип или замена для исходных массивов C. Он не имеет конструктора по умолчанию и не будет инициализироваться, если вы не выполните инициализацию значения. Пример: std::array<T> где T - POD.

  • Класс B является параметром шаблона. При отсутствии каких-либо ограничений на B инициализация значений является единственным безопасным выбором. B может быть std::array, в конце концов.

  • Класс B не работает. Его члены будут правильно инициализированы, если его экземпляры инициализируются значением. Он должен быть исправлен.