В чем разница между этим:
TestClass t;
И это:
TestClass t = TestClass();
Я ожидал, что второй может вызвать конструктор дважды, а затем оператор =, но вместо этого он вызывает конструктор ровно один раз, как и первый.
В чем разница между этим:
TestClass t;
И это:
TestClass t = TestClass();
Я ожидал, что второй может вызвать конструктор дважды, а затем оператор =, но вместо этого он вызывает конструктор ровно один раз, как и первый.
TestClass t;
вызывает конструктор по умолчанию.
TestClass t = TestClass();
является инициализацией копии. Он будет вызывать конструктор по умолчанию для TestClass()
, а затем конструктор копирования (теоретически копирование подлежит копированию). Здесь нет назначения.
Также существует понятие прямой инициализации:
TestClass t(TestClass());
Если вы хотите использовать оператор присваивания:
TestClass t;
TestClass s;
t = s;
Первый случай довольно прост - создает экземпляр с использованием конструктора по умолчанию.
Второй класс - это создание анонимного объекта, а затем вызов конструктора копирования. Обратите внимание, что здесь =
не присваивается, он похож на (но не идентичный):
TestClass t(TestClass());
Мы можем убедиться, что для этого необходим конструктор копирования, если он недоступен, например:
#include <iostream>
struct TestClass {
TestClass() { std::cout << "Ctor" << std::endl; }
TestClass(const TestClass&) = delete;
};
int main() {
TestClass t = TestClass();
}
Что не удается скомпилировать из-за конструктора удаленной копии. (В С++ 03 вы можете использовать private:
).
Что на самом деле происходит, скорее всего, это то, что ваш компилятор делает "Оптимизация возвращаемого значения" , благодаря чему он позволяет обойти вызов конструктору копирования полностью обеспечена подходящая, существует и будет доступна.
В первом вы вызываете конструктор по умолчанию неявно. А во втором вы вызываете его явно.
Последний может вызвать конструктор копирования и, следовательно, должен быть общедоступным.
Изменить: Я, конечно, сделал слишком большие выводы из имени типа, которое вы использовали. Вышеприведенное предложение применяется только для типов классов (т.е. Не POD). Для типов POD первая оставляет переменную неинициализированной, а последняя инициализирует ее так называемым значением по умолчанию.