В этом коде:
#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
?
Я заранее прошу прощения, если это глупый вопрос.
Спасибо!
Копирование / перемещение elision является единственным разрешенным исключением из так называемого «как будто«правило, которое обычно ограничивает виды преобразований (например, оптимизаций), которые компилятору разрешено выполнять в программе.
Правило предназначено для того, чтобы компиляторы могли выполнять любую оптимизацию, какую пожелают, до тех пор, пока будет работать преобразованная программа «.как будто«Это был оригинальный. Однако, есть одно важное исключение.
В соответствии с пунктом 12.8 / 31 стандарта C ++ 11:
При соблюдении определенных критериев реализация может опустить конструкцию копирования / перемещения класса.
объект, даже если выбран конструктор для операции копирования / перемещения и / или деструктор для объекта
имеют побочные эффекты. […] Это исключение операций копирования / перемещения, называемых разрешением копирования, допускается в следующих обстоятельствах (которые
могут быть объединены для устранения нескольких копий):[…]
- в
return
оператор в функции с типом возвращаемого класса, когда выражение является именем
энергонезависимый автоматический объект (отличный от параметра функции или оператора catch) с тем же cv-unqualified
type в качестве типа возврата функции, операция копирования / перемещения может быть опущена путем конструирования
автоматический объект непосредственно в возвращаемое значение функции[…]
- когда временный объект класса, который не был связан со ссылкой (12.2), будет скопирован / перемещен
для объекта класса с таким же cv-неквалифицированным типом, операция копирования / перемещения может быть опущена
построение временного объекта непосредственно в цель пропущенного копирования / перемещения
Другими словами, вы никогда не должны полагаться на конструктор копирования или конструктор перемещения, вызываемый или не вызывается в случаях, к которым применяются положения 12.8 / 31.
Других решений пока нет …