Я использую следующий фрагмент кода для сравнения двух методов создания объекта в C ++.
#include <iostream>
using std::cout;
using std::endl;
class Foo {
public:
Foo() : x(0) { cout << "In Foo constructor." << endl; }
~Foo() { cout << "In Foo destructor." << endl; }
Foo(const Foo&) { cout << "In Foo copy constructor." << endl; }
// Assignment operator.
Foo& operator=(const Foo&) {
cout << "In assignment operator." << endl;
return *this;
}
private:
int x;
};
int main() {
cout << "Constructing Foo 1" << endl;
Foo Foo_1;
cout << "Constructing Foo 2" << endl;
Foo Foo_2 = Foo();
return 0;
}
Вывод из этого фрагмента кода:
Constructing Foo 1
In Foo constructor.
Constructing Foo 2
In Foo constructor.
In Foo destructor.
In Foo destructor.
я использую Visual C ++ 2010 (версия компилятора 16.x), и я компилирую фрагмент с помощью cl /EHsc /W4 test.cpp
, В строительстве Foo_2
Я ожидал увидеть дополнительный вызов конструктора и деструктора для создания временного объекта и вызова оператора присваивания для назначения временного объекта Foo_2
, Может кто-нибудь объяснить мне, почему это не так. Извиняюсь, если я упускаю что-то очень очевидное здесь.
Существует две формы инициализации, доступные для Foo
:
Foo f1;
Foo f2 = Foo();
Первые конструкции f
напрямую, используя конструктор по умолчанию. Второй создает временный тип Foo
, используя конструктор по умолчанию, и копирует этот временный в f2
, Последнее, что вы описываете как то, что вы ожидали. И вы правы, за исключением одного дополнительного правила: если эта форма инициализации действительна (она здесь; сделайте конструктор копирования закрытым и посмотрите, что произойдет), компилятору разрешается «исключать» конструкцию и конструкцию копии. f2
напрямую, как и в первой версии. Это то, что вы видите. Компилятору не требуется исключать конструктор копирования, но каждый, что я недавно использовал, делает.
Foo Foo_2 = Foo();
похож на Foo Foo_2(Foo());
, Компилятор достаточно умен, чтобы сделать это, оператор присваивания не вызывается. Кстати, у вас есть ошибка в операторе присваивания — вы возвращаете ссылку на свой объект, а не копируете его.
Самая первая проблема «Гуру Недели» как раз о вашем вопросе http://www.gotw.ca/gotw/001.htm
Особенно примечание по оптимизации компилятора.