Прасун уже дал вам очень хороший ответ .Тем не менее, я хотел бы сделать еще одно замечание, которое мне не удалось втиснуть в комментарий:
Я видел эту ошибку (пренебрежение списками инициализации), сделанную новичками в C ++, которые пришлииз языков (Java, C #), где все типы являются либо примитивами, либо ссылками.Нет ничего сложного в том, чтобы по умолчанию инициализировать ссылку на сложный тип с null
, а затем перезаписать ее реальным объектом.Однако в C ++ типы имеют семантическое значение, если только семантическая ссылка не выбрана явно (и не реализована).
Думайте о том, что T
является дорогим для инициализации типом.(Для любого определения «дорого». Если у вас возникли проблемы с представлением такого типа, просто представьте, что мы говорим о коде драйвера графической карты. Почти все дорого для такого кода.) Поскольку вы можете свободно обращаться к объекту втело конструктора должно быть уже построено, когда тело конструктора выполнено.В противном случае вы получите доступ к необработанной памяти вместо действительного объекта.(Конструкция - это то, что превращает блоб необработанной памяти в действительный объект.)
Поэтому, когда вы присваиваете что-то объекту в теле конструктора, вы присваиваете уже полностью построенный объект.Поскольку вы не указали конструктор, объект будет создан с использованием конструктора по умолчанию.Это означает, что объект сначала будет создан по умолчанию, просто чтобы его значение по умолчанию было перезаписано чем-то другим в самый следующий момент.
Это, конечно, глупость, поэтому у нас есть списки инициализации.Используя их, мы можем указать компилятору, какие конструкторы он должен использовать для создания базового класса и дочерних подобъектов.Таким образом, объекты создаются с правильным значением немедленно.
Кроме того, как вы обнаружили, списки инициализации являются единственным способом инициализации определенных элементов данных, а именно константных объектов, ссылок и объектов типов, которые не имеют доступного конструктора по умолчанию.