temp temp1;
Это вызывает конструктор temp
по умолчанию для экземпляра с именем temp1
.
temp temp2 = temp();
Это вызывает конструктор temp
по умолчанию для временного объекта, затем вызывает сгенерированный компилятором конструктор копирования на temp2
с временным объектом в качестве аргумента (это, конечно, предполагает, что компилятор не исключает копии ; это зависит от настроек оптимизации вашего компилятора).
Что касается того, почему вы получаете разные инициализированные значения, уместен раздел 8.5 стандарта:
8.5 Инициализаторы [dcl.init]
Параграф 5:
К
Инициализация нуля Объект типа
T
означает:
- если
T
является скалярным типом (3.9), объекту присваивается значение 0 (ноль), преобразованное в T
;
- , если
T
является типом класса, не являющимся объединением, каждый нестатический элемент данных и каждый подобъект базового класса инициализируются нулями;
- , если
T
является типом объединения, первый именованный элемент данных объекта инициализируется нулями;
- если
T
является типом массива, каждый элемент инициализируется нулями;
- , если
T
является ссылочным типом, инициализация не выполняется.
К инициализация по умолчанию объект типа T
означает:
- , если
T
является типом класса, отличным от POD (пункт 9), вызывается конструктор по умолчанию для T
(и инициализация некорректна, если T
не имеет доступного конструктора по умолчанию);
- если
T
является типом массива, каждый элемент инициализируется по умолчанию;
- в противном случае объект инициализируется нулями.
Инициализация значения объекта типа T
означает:
- , если
T
является типом класса (раздел 9) с объявленным пользователем конструктором (12.1), то вызывается конструктор по умолчанию для T
(и инициализация некорректна, если T
не имеет доступных конструктор по умолчанию);
- если
T
является типом класса без объединения без объявленного пользователем конструктора, то каждый нестатический член данных и компонент базового класса T инициализируется значением;
- если
T
является типом массива, то каждый элемент инициализируется значением;
- в противном случае объект инициализируется нулями.
Пункт 7:
Объект, инициализатором которого является пустой набор скобок, т.е. (), должен быть инициализирован значением.
Пункт 9:
Если для объекта не указан инициализатор, и объект имеет (возможно, cv-квалифицированный) тип не-POD класса (или его массив), объект должен инициализироваться по умолчанию ; если объект имеет константный тип, базовый тип класса должен иметь объявленный пользователем конструктор по умолчанию. В противном случае, если инициализатор не указан для нестатического объекта, объект и его подобъекты, если таковые имеются, имеют неопределенное начальное значение; если объект или любой из его подобъектов имеют константный тип, программа является некорректной.
12 Специальные функции-члены [special]
Пункт 7:
Неявно объявленный конструктор по умолчанию для класса неявно определяется, когда он используется для создания объекта своего типа (1.8). Неявно определенный конструктор по умолчанию выполняет набор инициализаций класса, которые будут выполняться пользовательским конструктором по умолчанию для этого класса с пустым списком mem-initializer-list (12.6.2) и пустым телом функции.
12.6.2 Инициализация баз и членов [class.base.init]
Пункт 4:
Если данный нестатический элемент данных или базовый класс не назван с помощью mem-initializer-id (включая случай, когда нет mem-initializer-list, потому что конструктор не имеет ctor -инициализатор), затем
- Если объект является нестатическим членом данных типа (возможно, cv-квалифицированного) класса (или его массива) или базового класса, а класс объекта является классом, отличным от POD, объект инициализируется по умолчанию (8.5). Если сущность является нестатическим членом данных типа с константой, класс сущности должен иметь объявленный пользователем конструктор по умолчанию.
- В противном случае объект не инициализируется. Если сущность имеет константный тип или ссылочный тип, или (возможно, cv-квалифицированный) тип POD-класса (или его массив), содержащий (прямо или косвенно) член типа 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;
или используете списки инициализаторов).