Страницы

Поиск по вопросам

пятница, 20 декабря 2019 г.

Почему инициализацию полей прописывают вне тела конструктора

#cpp #классы #конструктор #инициализация


Практически всегда в в примерах кода встречал инициализацию полей класса вне тела
конструктора:

MyClass(): a(1),b(2),c(3)
{ }


а не 

MyClass()
{
 a = 1;
 b = 2;
 c = 3;
}


Если оба варианта рабочие, в чем практическая польза от инициализации вне тела конструктора?
    


Ответы

Ответ 1



В первом случае у вас вызываются конструкторы для полей, и тем самым осуществляется инициализация полей.. Во втором случае у вас сначала вызываются конструкторы по умолчанию, и, если инициализаторы полей отсутствуют в их определении, то затем еще вызываются копирующие операторы присваивания, чтобы инициализировать соответствующим образом эти поля, что может быть в конечном итоге очень затратно. Представьте, например, что в конструкторе динамически выделяется память. Тогда затем в копирующем операторе присваивания эта память будет переопределяться. Кроме того может так оказаться, что какой-то член данных вообще не имеет конструктора по умолчанию, а только конструкторы с параметрами. В этом случае второй вариант вообще не будет компилироваться. Рассмотрите простой пример. Данная программа будет успешно компилироваться #include struct A { int x; A( int x ) : x( x ) {} }; struct B { A a; B() : a( 10 ) {} }; int main() { return 0; } Однако следующая программа компилироваться не будет #include struct A { int x; A( int x ) : x( x ) {} }; struct B { A a; B() { a = 10; } }; int main() { return 0; } так как отсутствует конструктор по умолчанию у класса A, который должен быть вызван до передачи управления управления в тело конструктора B

Ответ 2



В порядке вызова. Сначала поля класса инициализируется в списке инциализации (вариант 1). Если списка нет, то компилятор сделает его сам в том порядке, в котором поля объявлены в классе. Потом будет происходить то, что написано в теле конструктора (вариант 2). Для конкретно вашего примера разницы никакой, т.к. у вас используются простые типы данных. Дополнительных накладных расходов нет. Это имеет смысл для классов, которые в качестве полей имеют объекты других классов. Таким способом можно достичь несоздание объекта класса, если при инициализации какого-нибудь его поля произойдёт ошибка. Ну и для объектов других классов могут быть затраты на инициализацию объекта. Поэтому может получиться повторный вызов. Ну и последний аргумент - вариант 1 является хорошей практикой. Думаю, что-то ещё добавят в комментариях и других ответах.

Комментариев нет:

Отправить комментарий