вызовы конструктора и деструктора, участвующие в создании объекта

Я использую следующий фрагмент кода для сравнения двух методов создания объекта в 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, Может кто-нибудь объяснить мне, почему это не так. Извиняюсь, если я упускаю что-то очень очевидное здесь.

2

Решение

Существует две формы инициализации, доступные для Foo:

Foo f1;
Foo f2 = Foo();

Первые конструкции f напрямую, используя конструктор по умолчанию. Второй создает временный тип Foo, используя конструктор по умолчанию, и копирует этот временный в f2, Последнее, что вы описываете как то, что вы ожидали. И вы правы, за исключением одного дополнительного правила: если эта форма инициализации действительна (она здесь; сделайте конструктор копирования закрытым и посмотрите, что произойдет), компилятору разрешается «исключать» конструкцию и конструкцию копии. f2 напрямую, как и в первой версии. Это то, что вы видите. Компилятору не требуется исключать конструктор копирования, но каждый, что я недавно использовал, делает.

4

Другие решения

Foo Foo_2 = Foo(); похож на Foo Foo_2(Foo());, Компилятор достаточно умен, чтобы сделать это, оператор присваивания не вызывается. Кстати, у вас есть ошибка в операторе присваивания — вы возвращаете ссылку на свой объект, а не копируете его.

1

Самая первая проблема «Гуру Недели» как раз о вашем вопросе http://www.gotw.ca/gotw/001.htm
Особенно примечание по оптимизации компилятора.

1
По вопросам рекламы [email protected]