Конструктор Копии C++, временные файлы и семантика копии

Для этой программы

#include <iostream>
using std::cout;

struct C 
{
    C() { cout << "Default C called!\n"; }
    C(const C &rhs) { cout << "CC called!\n"; }
};

const C f()
{
    cout << "Entered f()!\n";
    return C();
}

int main()
{
    C a = f();
    C b = a;

    return 0;
}

вывод, который я получаю:

Entered f()!
Default C called!
CC called!

С тех пор f() возвращается значением, оно должно возвратить временный файл. Как T a = x; T a(x);, не был бы он вызывать конструктора копии для конструкции a, с временным файлом передал - в как его аргумент?

17
задан legends2k 24 February 2010 в 02:33
поделиться

3 ответа

Поскольку f () возвращается по значению, он должен возвращать временное значение. Поскольку T a = x; is T a (x); , не будет ли он вызывать конструктор копирования для построения a с временным переданным -in в качестве аргумента?

Найдите оптимизацию возвращаемого значения. По умолчанию это включено. Если вы работаете в Windows и используете MSVC 2005+, вы можете использовать / Od , чтобы отключить это и получить желаемый результат (или -fno-elide-constructors в GCC). Также для MSVC см. эту статью.

12.8 Копирование объектов класса

15 При соблюдении определенных критериев реализации разрешается опускать конструкцию копирования объекта класса, даже если конструктор копирования и / или деструктор для объекта имеют побочные эффекты .В таких случаях реализация рассматривает источник и цель пропущенной операции копирования как просто два разных способа ссылки на один и тот же объект, а уничтожение этого объекта происходит в более позднем из моментов, когда два объекта были бы уничтожены без оптимизации {{1} }.115 Это Исключение операций копирования разрешено в следующих обстоятельствах (которые могут быть объединены для удаления нескольких копий):

- в оператор return в функции с типом возврата класса, , когда выражение является именем энергонезависимого автоматического объекта с таким же cv-unqualified в качестве типа возвращаемого значения функции , операцию копирования можно опустить, создав автоматический объект непосредственно в возвращаемом функцией функции {{1} } value - в выражении throw, когда операнд является именем энергонезависимого автоматического объекта , операция копирования fr операнд объекта исключения (15.1) может быть опущен путем создания автоматического объекта непосредственно в объекте исключения

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

- когда объявление исключения для исключения { Обработчик {1}} (пункт 15) объявляет объект того же типа (за исключением cv-qualification) как объект исключения (15.1), операцию копирования можно опустить, рассматривая объявление-исключения как псевдоним для объекта исключения, если значение программы будет без изменений, за исключением для выполнения конструкторов и деструкторов для объекта, объявленного объявлением исключения.

Примечание: Акцент мой

14
ответ дан 30 November 2019 в 13:45
поделиться

Я полагаю, это называется оптимизация возвращаемого значения.

Я предполагаю, что когда f() возвращает C объект, объект выделяется в стековом пространстве вызывающего метода, поэтому не требуется копирование для инициализации C a. Это ваш вызываемый по умолчанию C.

C b = a

Это вызывает конструктор копирования, следовательно, ваш CC называется.

Кстати, пример на вики выглядит очень похожим на ваш код.

2
ответ дан 30 November 2019 в 13:45
поделиться

Это пример оптимизации возвращаемого значения (RVO) функции, которые поддерживает ваш компилятор.

Конструктор копирования может не вызываться при возврате по значению.

Используйте параметр -fno-elide-constructors в GCC, чтобы отключить эту функцию.

4
ответ дан 30 November 2019 в 13:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: