Почему конструктор копирования не вызывается?

В этом коде:

#include <iostream>

using std::cout;

class Foo {
public:
Foo(): egg(0) {}
Foo(const Foo& other): egg(1) {}

int egg;
};

Foo bar() {
Foo baz;
baz.egg = 3;
return baz;
}

int main(void) {
Foo spam(bar());
cout << spam.egg;
return 0;
}

выход 3в то время как я ожидал, что это будет 1,

Это означает, что конструктор копирования не вызывается в строке Foo spam(bar()),

Я думаю, это потому, что bar функция не возвращает ссылку.

Не могли бы вы объяснить, что на самом деле происходит при инициализации spam?

Я заранее прошу прощения, если это глупый вопрос.

Спасибо!

10

Решение

Копирование / перемещение elision является единственным разрешенным исключением из так называемого «как будто«правило, которое обычно ограничивает виды преобразований (например, оптимизаций), которые компилятору разрешено выполнять в программе.

Правило предназначено для того, чтобы компиляторы могли выполнять любую оптимизацию, какую пожелают, до тех пор, пока будет работать преобразованная программа «.как будто«Это был оригинальный. Однако, есть одно важное исключение.

В соответствии с пунктом 12.8 / 31 стандарта C ++ 11:

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

  • в return оператор в функции с типом возвращаемого класса, когда выражение является именем
    энергонезависимый автоматический объект (отличный от параметра функции или оператора catch) с тем же cv-unqualified
    type в качестве типа возврата функции, операция копирования / перемещения может быть опущена путем конструирования
    автоматический объект непосредственно в возвращаемое значение функции
[…]
  • когда временный объект класса, который не был связан со ссылкой (12.2), будет скопирован / перемещен
    для объекта класса с таким же cv-неквалифицированным типом, операция копирования / перемещения может быть опущена
    построение временного объекта непосредственно в цель пропущенного копирования / перемещения
[…]

Другими словами, вы никогда не должны полагаться на конструктор копирования или конструктор перемещения, вызываемый или не вызывается в случаях, к которым применяются положения 12.8 / 31.

17

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]