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() возвращается по значению, он должен вернуть временное. As T a = x; is T a(x);, не вызовет ли он конструктор копирования для построения a, С временной передачей в качестве аргумента?

3 ответов


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

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

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

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

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

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

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

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


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

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

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


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

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

C b = a

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

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