Означает ли возврат по значению дополнительные копии и дополнительные издержки? 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 чтобы получить все две копии.

Другие вопросы по тегам