Означает ли возврат по значению дополнительные копии и дополнительные издержки? C++
Учтите следующее:
class Foo { ... };
Foo rbv();
void caller()
{
Foo x = rbv(); ← the return-value of rbv() goes into x
...
}
Foo rbv()
{
...
return Foo(42, 73); ← suppose Foo has a ctor Foo::Foo(int a, int b)
}
Сколько объектов типа Foo будет построено?
2 ответа
Может быть.
В C++11 значения возвращаются перемещением, а не копированием, если они имеют конструктор перемещения. Это может быть намного эффективнее, чем копирование.
В некоторых случаях, например, при возврате локальной или временной переменной (как здесь), перемещение или копирование могут быть исключены. Значение создается непосредственно в кадре стека вызывающего, так что его не нужно перемещать или копировать при возврате. Люди, которым нравятся сокращения, иногда называют это (N)RVO - (Именованное) Оптимизация возвращаемого значения.
Аналогично, копия или переход от временного возвращаемого значения к x
также может быть исключен.
Любой достойный компилятор будет реализовывать эту оптимизацию, поэтому ваш код должен создавать только один Foo
, Вы можете убедиться в этом, заставив деструктор напечатать сообщение и заметив, что он делает это только один раз: http://ideone.com/xydJqY. Если вы отключите оптимизацию, может быть до трех объектов.
Может быть до двух экземпляров: один из временного Foo(42, 73)
к возвращаемому значению функции, а другое от возвращаемого значения функции к x
, Однако обе эти копии имеют право на исключение копий, что позволяет не делать копии и вместо этого создавать объект непосредственно в месте назначения, что эквивалентно Foo x(42, 73);
,
Вы можете контролировать степень, в которой ваш компилятор использует преимущество копирования; например, в GCC вы можете использовать -fno-elide-constructors
чтобы получить все две копии.