Приведение к rvalue ссылки на «форсирование» перемещения возвращаемого значения - уточнение - PullRequest
0 голосов
/ 19 сентября 2018

Хорошо, я начинаю получать список ссылок на rvalue (я думаю).У меня есть фрагмент кода, который я писал:

#include <iostream>

using namespace std;

std::string get_string()
{
  std::string str{"here is your string\n"};
  return std::move(str);  // <----- cast here?
}

int main ()
{
  std::string my_string = std::move(get_string()); // <----- or cast here?
  std::cout << my_string;
  return 0;
}

Итак, у меня есть простой пример, где у меня есть функция, которая возвращает копию строки.Я прочитал, что это плохо (и получил дампы ядра, чтобы доказать это!), Чтобы вернуть любую ссылку на локальную временную переменную, поэтому я не пытался это делать.

В присваивании в main() Я неЯ хочу скопировать-создать эту строку. Я хочу переместить-построить / назначить строку, чтобы избежать слишком частого копирования строки.

  • Q1: я возвращаю «копию» временного varв get_string() - но я привел возвращаемое значение к rvalue-red.Это бессмысленно или это делает что-нибудь полезное?

  • Q2: Предполагая, что ответ Q1 - мне не нужно этого делать.Затем я перемещаю новую копию временной переменной в my_string, или я перемещаю непосредственно временную переменную str в my_string.

  • Q3: какой минимумколичество копий, которое вам нужно, чтобы получить возвращаемое строковое значение, сохраненное во «внешней» (в моем случае в переменной main ()), и как вы это делаете (если я этого еще не достиг)?

Ответы [ 2 ]

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

Вам не нужно использовать std::move для возвращаемого значения, которое является локальной переменной. Компилятор сделает это за вас :

Если выражение - это выражение lvalue, которое (возможно заключенное в скобки) имя объекта длительности автоматического хранения, объявленного в теле или в качестве параметрасамой внутренней включающей функции или лямбда-выражения, затем разрешение перегрузки для выбора конструктора, который будет использоваться для инициализации возвращаемого значения, выполняется дважды: сначала, как если бы выражение было выражением rvalue (таким образом оно может выбрать конструктор перемещения), и, если оно не подходитпреобразование доступно, или если тип первого параметра выбранного конструктора не является rvalue-ссылкой на тип объекта (возможно, cv-квалифицирован), разрешение перегрузки выполняется во второй раз, причем выражение рассматривается как lvalue (так что оно можетвыберите конструктор копирования, ссылаясь на неконстантный).

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

Я возвращаю «копию» временного var в get_string () - но я привел возвращаемое значение к rvalue-red.Это бессмысленно или это делает что-нибудь полезное?

Вам не нужно использовать std::move в этой ситуации, поскольку локальные переменные, возвращаемые значением, «неявно перемещаются» для вас.Для этого в Стандарте есть специальное правило.В этом случае ваш ход пессимизирует , поскольку он может предотвратить RVO (clang предупреждает об этом).


Q2: Предполагая, что ответ Q1 - мне не нужносделай это.Затем я перемещаю свежую копию временной переменной в my_string, или я перемещаю непосредственно временную переменную str в my_string.

Вам не нужно std::move результат вызова get_string().get_string() - это prvalue , что означает, что автоматически будет вызван конструктор перемещения my_string (до C ++ 17).В C ++ 17 и выше, обязательное копирование elision гарантирует, что никаких перемещений / копий не произойдет (с prvalues ​​).


В3: какое минимальное количество копий вам нужно, чтобы получить строковое возвращаемое значение, сохраненное во «внешней» (в моем случае в переменной main ()), икак вы это делаете (если я еще не достиг этого)?

Зависит от Стандарта и от того, имеет ли место RVO.Если произойдет RVO, у вас будет 0 копий и 0 ходов.Если вы нацелены на C ++ 17 и инициализируете с prvalue , у вас гарантированно будет 0 копий и 0 ходов.Если ни то, ни другое не произойдет, у вас, вероятно, будет один ход - я не понимаю, почему здесь должна происходить какая-либо копия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...