Ответ 1
temp temp1;
Это вызывает конструктор по умолчанию temp
по умолчанию в экземпляре temp1
.
temp temp2 = temp();
Это вызывает конструктор по умолчанию temp
по временному объекту, затем вызывает созданный компилятором экземпляр-конструктор на temp2
с временным объектом в качестве аргумента (это, конечно, предполагает, что компилятор не удаляет копии; зависит от ваших настроек оптимизации компилятора).
Что касается того, почему вы получаете разные инициализированные значения, применим раздел 8.5 стандарта:
8.5 Инициализаторы [dcl.init]
Пункт 5:
Для нулевой инициализации объекта типаT
означает:
- если
T
является скалярным типом (3.9), объект устанавливается в значение 0 (ноль), преобразованное вT
; - if
T
- тип неединичного класса, каждый нестатический член данных и каждый подобъект базового класса инициализируются нулем; - if
T
- это тип объединения, объекты, сначала названные членами данных, инициализируются нулем; - if
T
- тип массива, каждый элемент инициализируется нулем; - Если
T
является ссылочным типом, инициализация не выполняется.
Для инициализации по умолчанию объекта типа T
означает:
- Если
T
- тип класса не-POD (раздел 9), вызывается конструктор по умолчанию дляT
(и инициализация плохо сформирована, еслиT
не имеет доступного конструктора по умолчанию); - if
T
- тип массива, каждый элемент инициализируется по умолчанию; - в противном случае объект инициализируется нулем.
Для инициализации объекта с типом T
означает:
- if
T
- это тип класса (раздел 9) с объявленным пользователем конструктором (12.1), тогда вызывается конструктор по умолчанию дляT
(и инициализация плохо сформирована, еслиT
не имеет доступного конструктор по умолчанию); - if
T
- это неединичный тип класса без конструктора, объявленного пользователем, то каждый нестатический элемент данных и компонент базового класса T инициализируются значением; - if
T
- тип массива, тогда каждый элемент инициализируется значением; - в противном случае объект инициализируется нулем.
Пункт 7:
Объект, инициализатор которого представляет собой пустой набор круглых скобок, т.е.(), должен инициализироваться значением.
Пункт 9:
Если для объекта не указан инициализатор, и объект имеет (возможно, cv-квалифицированный) тип класса не-POD (или его массив), объект должен иметь значение по умолчанию, инициализируется; если объект имеет тип const-type, базовый тип класса должен иметь объявленный пользователем конструктор по умолчанию. В противном случае, если для нестатического объекта не указан инициализатор, объект и его подобъекты, если они есть, имеют неопределенное начальное значение; если объект или какой-либо из его подобъектов имеют тип const-specific, программа плохо сформирована.12 Специальные функции членов [специальные]
Пункт 7:
Неявно объявленный конструктор по умолчанию для класса неявно определяется, когда он используется для создания объекта его типа класса (1.8). Неявно определенный конструктор по умолчанию выполняет набор инициализаций класса, который будет выполняться написанным пользователем конструктором по умолчанию для этого класса с пустым списком mem-initializer (12.6.2) и пустым телом функции.12.6.2 Инициализация баз и членов [class.base.init]
Пункт 4:
Если данный нестатический член данных или базовый класс не назван идентификатором mem-initializer (включая случай, когда нет списка mem-initializer, поскольку у конструктора нет ctor-initializer), то- Если объект является нестатистическим членом данных (возможно, cv-qualified) типа класса (или его массива) или базового класса, а класс сущности - не-POD-класс, объект инициализируется по умолчанию (8.5), Если объект является нестатистическим членом данных типа, соответствующего const, класс сущности должен иметь объявленный пользователем конструктор по умолчанию.
- В противном случае объект не инициализируется. Если объект имеет тип или ссылочный тип с константным кодом или тип (или его тип) класса POD (возможно, cv-qualified), содержащий (прямо или косвенно) член определенного типа const, формируется.
Итак, теперь, когда правила были изложены, давайте посмотрим, как они применяются:
temp temp1;
temp
является не-POD-типом (поскольку он имеет член std::string
), и поскольку для temp1
не указан инициализатор, он будет инициализирован по умолчанию (8.5/9). Это вызывает конструктор по умолчанию (8.5/5). temp
имеет неявный конструктор по умолчанию (12/7), который по умолчанию инициализирует член std::string
, а элемент int
вообще не инициализируется (12.6.2/4).
temp temp2 = temp();
С другой стороны, временный объект temp
инициализируется значением (8.5/7), значение которого инициализирует все члены данных (8.5/5), который вызывает конструктор по умолчанию в элементе std::string
и ноль -инициализирует член int
(8.5/5).
Конечно, если вам больше не нужно ссылаться на стандарт в 5+ разных местах, просто убедитесь, что вы явно инициализируете все (например, int i = 0;
или используя списки инициализаторов).