Список инициализации конструктора начинается с двоеточия, за которым следует разделённый запятыми список членов данных, каждый член данных сопровождается инициализатором в круглых скобках. Например:
class CExample {
public:
int a;
float b;
//构造函数初始化列表
CExample(): a(0),b(8.8)
{}
//构造函数内部赋值
CExample()
{
a=0;
b=8.8;
}
};
В приведённом выше примере результаты двух конструкторов одинаковы. Приведённый выше конструктор (тот, который использует список инициализации) явно инициализирует члены класса; тогда как конструктор, не использующий список инициализации, присваивает значения членам класса без явной инициализации.
Инициализация и присваивание почти не отличаются для членов встроенных типов, поэтому подходит любой из приведённых выше конструкторов. Для переменных-членов невстроенных типов, чтобы избежать двойного конструирования, рекомендуется использовать список инициализации конструктора класса. Но иногда конструктор со списком инициализации обязателен:
- 1. Тип члена —класс без конструктора по умолчанию. Если явный инициализатор не предоставлен, компилятор неявно использует конструктор по умолчанию для этого типа члена. Если у класса нет конструктора по умолчанию, попытка компилятора использовать конструктор по умолчанию завершится неудачей.члены const
- 2.члены constиличлены ссылочного типа. Поскольку объекты const или ссылочные типы можно только инициализировать, но не присваивать им значения.
Что означает инициализировать члены данных в отличие от присваивания значений членам данных? В чём разница?
Сначала классифицируем члены данных по типу и объясним каждый случай:
- 1.Встроенные типы данных, составные типы (указатели, ссылки)- выполнение этого в списке инициализации членов или в теле конструктора одинаково как по производительности, так и по результату.
- 2.Пользовательские типы (классовые типы)- Результаты одинаковы, но есть большая разница в производительности. Поскольку объекты-члены данных классового типа уже сконструированы до входа в тело функции, то есть работа по конструированию выполняется в списке инициализации членов, вызывая конструктор. После входа в тело функции выполняется присваивание значений уже сконструированным объектам класса, что требует вызова оператора присваивания копированием (если он не предоставлен, используется предоставляемое компилятором поведение поэлементного присваивания по умолчанию).
Примечания:
Порядок инициализации членов в списке инициализации:
C++ инициализирует члены класса в порядке их объявления, а не в порядке их появления в списке инициализации.
class CMyClass {
CMyClass(int x, int y);
int m_x;
int m_y;
};
CMyClass::CMyClass(int x, int y) : m_y(y), m_x(m_y)
{
};
Вы можете подумать, что приведённый выше код сначала выполнит m_y=I, затем m_x=m_y, и в конце они будут иметь одинаковое значение. Но компилятор инициализирует m_x первым, затем m_y, потому что они объявлены в таком порядке. В результате m_x будет иметь непредсказуемое значение. Есть два способа избежать этого: первый — всегда объявлять члены в том порядке, в котором вы хотите их инициализировать; второй — если вы решили использовать список инициализации, всегда перечисляйте члены в порядке их объявления. Это поможет устранить путаницу.
Исходный адрес: http://www.cnblogs.com/BlueTzar/articles/1223169.html