Почему return не копирует объект?

Следующий код печатает только A::A(), но нет A::A(const A&) или же operator=, Зачем?

struct A
{
A()               { cout << "A::A()" << endl; }
A(const A& value) { cout << "A::A(const A&)" << endl; }

A& operator=(const A& newValut)
{
cout << "A::operator=" << endl;
return *this;
}
};

A foo()
{
A a;      //Ok, there we have to create local object by calling A::A().
return a; //And there we need to copy it, otherwise it will be destroyed
//because it's local object. But we don't.
}

int main()
{
A aa = foo(); //Also there we need to put result to the aa
//by calling A::A(const A&), but we don't.
}

Так что этот код должен напечатать

A::A()
A::A(const A&)
A::A(const A&)

Но это не так. Зачем?

Я полагаю, что нет foo() под g++ без оптимизации.

0

Решение

Это называется «Оптимизация возвращаемого значения». Компилятору разрешено исключать копию в таком случае.

10

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

Вот как в C ++ осуществляется возврат сложного типа: местоположение возвращаемого объекта фактически предоставляется вызывающей стороной до вызова функции, и указатель на этот еще не инициализированный объект передается в качестве скрытого аргумента функции. Функция использует эту ячейку памяти для конструирования возвращаемого объекта из возвращенного выражения.

Поэтому, когда возвращаемый объект должен напрямую инициализировать новый объект, как в вашей программе A aa = foo();, ему не нужно копировать возвращаемое значение в объект в стеке. Он просит функцию создать объект непосредственно в этом месте. Таким образом, должен быть сделан только один вызов конструктора копирования. (На самом деле, если бы у вас было 2 вызова конструктора копирования, компилятор C ++ не был бы совместимым).

Кроме того, компилятору разрешено оптимизировать этот вызов с помощью оптимизации под названием «Оптимизация возвращаемого значения» или RVO. Как это возможно? Если вы посмотрите на свой код, вы увидите, что вы можете напрямую определить локальную переменную «a» в foo () в предполагаемом месте возвращаемого значения, и, следовательно, не нужно копировать ее снова. Это важная функция, потому что конструктор копирования может быть сложным и медленным, поэтому он может значительно повысить производительность при реализации (и каждый известный мне компилятор реализует эту функцию).

Так что в вашем случае, в зависимости от компилятора, у вас может быть 1 или 0 вызов конструктора копирования, и ваш компилятор все еще совместим.

3

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector