Преимущества списков инициализации
Из того, что я знаю о преимуществах использования списка инициализации, заключается в том, что они обеспечивают эффективность при инициализации членов класса, которые не являются встроенными. Например,
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;
};
Ответы
Ответ 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
Мы также можем выполнить конструктор через список инициализации.