Скопировать конструктор elision?

Возможный дубликат:
Почему деструктор был вызван только один раз?

Учитывая код ниже, я не понимаю вывод в gcc. Я ожидаю, что два объекта будут созданы и уничтожены, но вместо этого я вижу только один вызов конструктора и деструктора. Что тут происходит?

#include <string>
#include <iostream>

struct Huge{
        Huge() { std::cout << "Constructor" << std::endl; }
        Huge(Huge const &r) { std::cout << "Copy Constructor" << std::endl; }
        ~Huge() { std::cout << "Destructor" << std::endl; }
};

Huge g() {
        std::cout << "Entering g" << std::endl;
        Huge temp;
        std::cout << "Exiting g" << std::endl;
        return temp;
}

int main(){
        Huge h2(g());
        std::cout << "Before leaving main" << std::endl;
}

Вывод этого кода в g++ (4.4)

Ввод г

Конструктор

Выход г

Перед выходом из основного

Destructor

2 ответа

Решение

Да, это копирование с помощью оптимизации именованных возвращаемых значений.

Стандарт C++ позволяет реализации опустить операцию копирования, являющуюся результатом оператора return, даже если конструктор копирования имеет побочные эффекты.

Ссылка:

Стандарт C++03:
12.8 Копирование объектов класса:

№ 15

Когда определенные критерии выполнены, реализация может опустить конструкцию копирования объекта класса, даже если конструктор копирования и / или деструктор для объекта имеют побочные эффекты. В таких случаях реализация рассматривает источник и цель пропущенной операции копирования как просто два разных способа обращения к одному и тому же объекту, и уничтожение этого объекта происходит в более поздние времена, когда два объекта были бы уничтожены без Оптимизация.111) Это исключение операций копирования допускается при следующих обстоятельствах (которые могут быть объединены для устранения нескольких копий):

- в операторе return в функции с типом возврата класса, когда выражение является именем энергонезависимого автоматического объекта с тем же типом cv-unqualified, что и тип возврата функции, операция копирования может быть опущена путем создания автоматического объект непосредственно в возвращаемое значение функции

- когда временный объект класса, который не был связан со ссылкой (12.2), будет скопирован в объект класса с тем же типом cv-unqualified, операция копирования может быть опущена путем создания временного объекта непосредственно в цель опущенного копия

C++ позволяет избежать создания и копирования дополнительных объектов в таких случаях, как ваш. Это известно как названная оптимизация возвращаемого значения. Дело в том, что вы точно знаете, что после возврата объекта temp в любом случае исчезнет, ​​и семантика конструктора копирования должна состоять в том, чтобы сделать точно эквивалентную копию оригинальному объекту.

Обратите внимание, что на самом деле здесь происходят две оптимизации. Без оптимизации, объект temp будет сначала скопирован в возвращаемое значение в g, а затем возвращаемое значение будет скопировано в h2 в main, Оптимизация именованного возвращаемого значения исключает копию в возвращаемое значение. Копирование из возвращаемого значения в h2 исключается, потому что возвращаемое значение является временным объектом, и в этом случае создание копии также может быть исключено.

Обратите внимание, что в отличие от других оптимизаций, эти оптимизации разрешены, даже если они изменяют наблюдаемое поведение (как в вашей тестовой программе). Это потому, что в противном случае эта оптимизация не может быть выполнена во многих случаях, когда она не имеет значения (действительно, за исключением отладки вывода, это никогда не должно иметь значения в хорошо написанной программе), потому что компилятор часто не может доказать, что elision не изменит наблюдаемого поведения. С другой стороны, невозможно вручную удалить копии, поэтому важно, чтобы компилятор мог сделать это автоматически.

В конечном итоге происходит то, что объект temp напрямую создается в космосе h2 занимает, так что в точке возврата оператора h2 уже содержит правильное значение. Другими словами, из-за оптимизации temp а также h2 на самом деле один и тот же объект.

Другие вопросы по тегам