Списки инициализации в конструкторе
Я слышал, что преимущество использования списков инициализации в конструкторе заключается в том, что не будет лишних копий объектов типа класса. Но что это значит для следующего кода в конструкторе класса T? Если я прокомментирую назначение и использую списки инициализации, какая будет разница?
#include <iostream>
using std::cout;
using std::endl;
using std::ostream;
class X {
public:
X(float f_x = 0, float f_y = 0):x(f_x), y(f_y) {}
~X() {}
X(const X& obj):x(obj.x), y(obj.y) {}
friend ostream& operator << (ostream &os, X &obj);
private:
float x;
float y;
};
ostream& operator << (ostream &os, X &obj)
{ os << "x = " << obj.x << " y = " << obj.y; return os;}
class T {
public:
T(X &obj) : x(obj) { /* x = obj */ }
~T() { }
friend ostream& operator << (ostream &os, T &obj);
private:
X x;
};
ostream& operator << (ostream &os, T &obj)
{ os << obj.x; return os; }
int main()
{
X temp_x(4.6f, 6.5f);
T t(temp_x);
cout << t << endl;
}
3 ответа
Это именно то, что вы уже сказали. Если вы не используете список инициализатора, то сначала будет вызван конструктор по умолчанию, а затем будет вызван оператор присваивания.
В вашем примере, это относительно мягко (думаю, компилятор может даже оптимизировать это). Но в других случаях просто невозможно избежать списка инициализаторов. Представь если X
не было публичного оператора присваивания.
Если вы используете Назначение, то:x
будет построен по умолчанию первым &
затем назначается с obj
,
Стоимость, Строительство по умолчанию + Назначение
Если вы используете список инициализаторов членов, то:x
будет построен и инициализирован с obj
,
Стоимость только строительство
T(X &obj) : x(obj) {}
скопирует конструкцию x из obj, а
T(X &obj){ x = obj; }
создаст значение по умолчанию x только для того, чтобы затем заменить его значениями из obj.
Если вы намереваетесь создать объект-член, вы должны сделать это в списке инициализации.