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

Преимущества списков инициализации

Из того, что я знаю о преимуществах использования списка инициализации, заключается в том, что они обеспечивают эффективность при инициализации членов класса, которые не являются встроенными. Например,

Fred::Fred() : x_(whatever) { }

предпочтительнее,

Fred::Fred() { x_ = whatever; }

если x - объект пользовательского класса. Помимо этого, этот стиль используется даже со встроенными типами для согласованности.

Наиболее распространенным преимуществом этого является улучшение производительности. Если выражение любого типа того же типа, что и переменная-член x_, результат любого выражения строится непосредственно внутри x_ - компилятор не создает отдельную копию объекта.

В другом стиле выражение, которое вызывает отдельный, временный объект, который будет создан, и этот временный объект передается в оператор назначения объекта x_. Затем этот временный объект разрушается в;; Это неэффективно.

Вопрос
Есть ли коэффициент усиления эффективности в следующем примере с использованием списка инициализации. Я думаю, что нет никакой выгоды. Первая версия вызывает конструктор строковых копий, а другой - оператор присваивания строк (нет временных созданий). Это правильно?

class MyClass
{
public:
    MyClass(string n):name(n) { }
private:
    string name;
};

class MyClass
{
public:
    MyClass(string n)
    {
        name=n;
    }
private:
    string name;
};
4b9b3361

Ответ 1

Вторая версия вызывает вызов по умолчанию ctor, а затем оператор string-assign-assign - там могут быть (незначительные) потери эффективности по сравнению с первой, которая напрямую вызывает c copy-ctor (например, в зависимости от реализации строки, возможно, будет бесполезное распределение-then-release некоторой крошечной структуры). Почему бы просто не использовать правильный путь? -)

Ответ 2

Я думаю, что единственный способ инициализировать элементы данных const находится в списке инициализации

Eg. в заголовке:

class C
{
    C();
private:
    const int x;
    int y;
}

И в файле cpp:

C::C() :
    x( 10 ),
    y( 10 )
{
    x = 20; // fails
    y = 20;
}

Ответ 3

Это отличный способ инициализировать членов, которые:

  • - const
  • не имеют конструктора по умолчанию (он закрыт)

Ответ 4

Помните, что между конструктором копирования и оператором присваивания существует четкое различие:

  • копия ctor создает новый объект, используя какой-либо другой экземпляр в качестве места для получения информации об инициализации.
  • оператор присваивания изменяет уже существующий объект, который уже полностью сконструирован (даже если он используется только с помощью конструктора по умолчанию)

Итак, в вашем втором примере уже проделана определенная работа по созданию name к тому времени, когда

 name=n;

.

Однако вполне возможно (особенно в этом простом примере), что выполненная работа исчезающе мала (возможно, просто обнуление некоторых элементов данных в объекте string) и что работа полностью оптимизирована в оптимизированной сборке. но по-прежнему считается хорошей формой использовать списки инициализаторов, когда это возможно.

Ответ 5

Ниже приведены сценарии использования списка инициализаторов:

  • Для инициализации нестатических членов данных const.
  • Для инициализации ссылочных элементов.
  • Для инициализации объектов-членов, не имеющих конструктора по умолчанию.
  • Для инициализации базовых классов.
  • Когда имя параметра конструктора совпадает с именем элемента данных.
  • По соображениям производительности.

Ответ 6

Мы также можем выполнить конструктор через список инициализации.