список инициализатора фигурной скобки как аргумент функции - PullRequest
0 голосов
/ 12 сентября 2018

Игнорируя разрешение на копирование / перемещение из компилятора, я хотел бы знать, если следующий код (при условии, что foo имеет конструктор, принимающий три целых числа) «синтаксически» создает временный объект, а затем копирует / перемещает инициализирует аргумент функции, илинапрямую вызывает конструктор:

void acceptsFoo(foo a);

acceptsFoo({1, 2, 3});

А как насчет этого случая?

//ignoring RVO optimization
foo returnsFoo()
{
   return {1, 2, 3};
}

Я знаю, что приведенный ниже код, даже без разрешения копирования / перемещения, аналогичен вызову конструкторапоэтому не будет генерировать временные данные, но я не смог найти информацию о коде выше.

foo = { 1, 2, 3 } //assuming the constructor is non-explicit
foo { 1, 2, 3 }

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018
void acceptsFoo(foo a);

acceptsFoo({1, 2, 3});

Нет, в этом случае не будет временного.Параметр инициализируется непосредственно из выражения аргумента.


//ignoring RVO optimization
foo returnsFoo()
{
   return {1, 2, 3};
}

Как и в случае с аргументом, возвращаемое значение инициализируется непосредственно из оператора return.

Однако результатом выражения вызова функции будет временный объект, да.Итак, если бы вы вызвали функцию следующим образом: foo f = returnsFoo(); Было бы создано два экземпляра.Сначала возвращаемое значение инициализируется из инициализатора фигурных скобок, затем объект, связанный с переменной, инициализируется копией из временного (путем перемещения, если foo является подвижным).

Это с точки зрения абстрактной машины;копирование / перемещение может быть исключено на практике (это то, что делает RVO).


Однако, начиная с C ++ 17, в операторе foo f = returnsFoo(); не будет ни временной, ни копии /перейти в элиду.С другой стороны, в операторе returnsFoo(); будет создан временный объект (который немедленно уничтожается).

0 голосов
/ 12 сентября 2018

Когда для инициализации объекта используется фигурный список инициализации, он используется для инициализации объекта.Период.

Применение фигурного списка инициализации к параметру функции означает инициализацию этого параметра списком значений в соответствии с правилами инициализации списка.Когда вы возвращаете braced-init-list, он используется для инициализации объекта возвращаемого значения списком значений в соответствии с правилами инициализации списка.

Нет временного объекта, теоретически копируемого впараметр / возвращаемое значение.

Сейчас (до C ++ 17), если вы сделали acceptsFoo(foo{1, 2, 3}); или return foo{1, 2, 3}, то это вызовет создание временного объекта, который затем будет использоваться для инициализациипараметр / возвращаемое значение.

...