Подтвердить что ты не робот

С++ Копировать конструктор, временные и семантику копирования

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

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

4b9b3361

Ответ 1

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

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

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

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

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

C b = a

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

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