| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > C/C++: Для новичков > Инициализатор элементов |
| Автор: hoz 27.4.2014, 12:48 | ||
Часто встречаю такие приёмы, когда переменные инициализируются посредством инициализатора элементов. Хочется понять это просто альтернатива, которая не является необходимой вообще или всё-таки бывает необходима? Например:
переменной x же можно было присвоить значение value внутри конструктора, зачем было объявлять его через : после заголовка? |
| Автор: BlackSpace 27.4.2014, 18:05 | ||
| hoz, да это альтернативный способ, но он боле эффективен для некоторых типов данных, ну а в некоторых случаях без него не обойтись. В C++ - при создании объекта все члены данных объекта должны быть созданы до вызова конструктора. Список инициализации позволяет задать начальные данные объекту в момент его создания. В процессе создания членов данных, которые сами являются объектами, должны быть вызваны конструкторы. В теле же конструктора, когда происходит присвоение значения объекту - объект не создается, а лишь модифицируется. Думаю тут понятно, что проще сразу присвоить нужные значения членам объекта, чем сначала присвоить то, что есть в конструкторе объекта, а потом менять. Плюс еще для const члена данных не прокатит присваивание. Только инициализация при создании. Также ссылочный тип данных. Вот пример с const.
|
| Автор: BlackSpace 27.4.2014, 23:35 | ||||||
| hoz, попробую пояснить на примерах. Пример 1.
Пример 2
1) Все члены данных объекта должны быть созданы до вызова конструктора. 2) Если у объекта класса N есть член данных, который является тоже объектом некого класса M, то до вызова конструктора класса N создается объект класса M. - Но как? С помощью своего конструктора. - А какие значения членам данных объекта класса M присваиваются? Такие, которые заложены в его соответствующем конструкторе. 3) Так вот список инициализации позволяет в момент создания объекта класса N - инициализировать его члены данных. Т.е. инициализировать в данном случае член класса M. По примерам выше поясню разницу. str является объектом класса string. В примере 1 член данных str инициализируется строкой 123 сразу в момент создания объекта класса A. В примере 2 член данных str инициализируется сначала своим конструктором по умолчанию, только потом происходит модификация строки, когда в теле конструктора присваивание происходит. Чувствуете отличие? В первом примере мы не вызывали конструктор по умолчанию для члена данных str, а использовали конструктор класса string с одним аргументом. Вот тут про эффективность думаю понять можно.
Ничего подобного. Ничего в данном случае не обходится. В классе есть константный член и он не меняется. Его надо как-то инициализировать же при создании объекта класса. Вот в списке инициализации и делается это. |
| Автор: borisbn 28.4.2014, 09:31 | ||||
Позволю себе дополнить пример BlackSpace
Вывод:
Вот - http://ideone.com/X4AvnZ - можешь "поиграться" |
| Автор: hoz 1.5.2014, 19:11 | ||||||||||
Согласен. Изначально отрабатывают конструкторы объектов, которые являются членами данного класса (В нашем случает объекта класса N). И, отрабатывают они, как я понимаю, в любом случае.
Это понятно.
А как же собственный конструктор класса string ? Судя по ответу, он типа не участвует в инициализации данных класса... А вместо него инициализация происходит напрямую в момент создания объекта класса А.
А вот тут я недопонимаю. Сразу не писал, пытался вникунуть, но.. Почему-то тут член данных str инициализируется изначально своим конструктором по умолчанию, а потом уже в теле конструктора. Удивляет меня то, что согласно теории, в любом учебнике сказано, что при создании объекта конструктор вызывается автоматически. Поэтому странно слышать, что в первом случае минуя автоматический конструктор по умолчанию член данных инициализируется сразу заданным значение. Это как понимать?
Как выше я написал, не стыковка выходит. Если согласно документации конструктор вызывается автоматически, и, всегда, то.. как его можно не вызывать? |
| Автор: feodorv 1.5.2014, 21:09 | ||||
hoz, конструкторов у одного и того же класса может быть несколько. Как с различающимися параметрами, так и без параметров (или с параметрами по умолчанию), последний случай и есть конструктор по умолчанию. Если пользователь явно указал вызов конструктора для какого-либо члена класса, то для него конструктор по умолчанию не вызывается (да и зачем, если и так был вызван другой конструктор с параметрами).
|
| Автор: hoz 1.5.2014, 23:45 | ||||
Но вызывается то один конструктор как ни крути. Хотя их может быть несколько..
А для остальных вызывается? Имею ввиду если членов класса, скажем так, - 10. Явно инициалируется 1 член. Тогда 9 оставшихся членов-данных инициализируются конструктором по умолчанию, верно? |
| Автор: BlackSpace 2.5.2014, 04:44 | ||||||
| hoz, В моем примере 1 для члена данных str вызывается один конструктор ( с одним параметром в данном случае ). И все. str сразу имеет нужный нам вид - "123". В примере 2 для того же str вызывается сначала конструктор по умолчанию, а лишь потом идет работа по модификации str. Во многих случаях гораздо эффективнее список инициализации, так как он позволяет избежать вызова конструктора по умолчанию ( после которого мы должны модифицировать поле ( str )в теле конструктора ( класса A ) ), а вызвать сразу нужный нам конструктор. А константные или ссылочные поля только в этом списке и можно инициализировать. Мой пример не демонстрирует непосредственно эффективность, но общий принцип должен быть понятен.
Так, приведу еще пример. Правда, 10 классов для примера я не стал писать. Думаю, что для примера сойдет 3 класса, которые будут типами полей в большем классе. Три ( одинаковых для простоты примера ) класса A, B и C. Все имеют конструктор по умолчанию и конструктор с одним параметром. Используемый конструктор можно отследить на стандартном выводе. Два ( почти одинаковых ) класса CommonFirst и CommonSecond, которые содержат поля типов A, B и C. Разница между двумя классами - в конструкторе с тремя параметрами.
Вывод программы
|
| Автор: vinter 2.5.2014, 17:22 | ||||
нет, в С++ есть делегирующие конструкторы, которые позволяют сделать цепочку вызова конструкторов сколь угодно длинной.
не у всех типов есть конструкторы. К примеру у базовых типов его нет. Для тех у которых есть конструктор по-умолчанию - да, вызывается. |
| Автор: xvr 5.5.2014, 16:59 |
Точнее появились в С++11 (так к слову |