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

StackOverflow https://stackoverflow.com/questions/2323225

Вопрос

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

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

Это было полезно?

Решение

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

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

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

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

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

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

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

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

Другие советы

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

Конструктор копирования могло бы и не быть будет вызван, когда вы вернетесь по значению.

Использование -fno-elide-constructors опция в GCC для отключения этой функции.

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

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

C b = a

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top