C ++ Copy конструктор, временные и копировальные семантики - PullRequest
17 голосов
/ 24 февраля 2010

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

#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 с временным передаваемым аргументом в качестве аргумента?

Ответы [ 3 ]

14 голосов
/ 24 февраля 2010

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

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

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

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

- в операторе возврата в функция с типом возвращаемого класса, когда выражение является именем энергонезависимый автоматический объект с тот же CV-неквалифицированный тип как тип возвращаемого значения, копия операция может быть опущена строительство автоматического объекта непосредственно в возвращении функции значение - в выражении броска, когда операнд это имя энергонезависимый автоматический объект, операция копирования из операнда в объект исключения (15.1) может быть опущен путем построения автоматического объекта непосредственно в объект исключения

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

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

Примечание: выделение мин

4 голосов
/ 24 февраля 2010

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

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

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

2 голосов
/ 24 февраля 2010

Мне кажется, это называется оптимизация возвращаемого значения .

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

C b = a

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

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

...