std:: перемещение объясняется на примере

#c

#c

Вопрос:

Я пытаюсь понять, как работает std::move, и я столкнулся с некоторыми проблемами: итак, это реализация:

 template <typename T>
typename remove_reference<T>::typeamp;amp; move(Tamp;amp; t){
     return static_cast<typename remove_reference::typeamp;amp;>(t);
 

Позвольте мне просмотреть этот фрагмент построчно, используя

 string s2;
s2 = std::move(string("hello"));
 
  1. конструктор для строки hello вернет значение rvalue .
  2. правила вывода типа говорят нам, что если я передаю rvalue параметруamp;amp;, то string в этом случае я получаю указанный тип.
  3. Теперь идет часть static_cast
  4. remove_reference<T> будет просто remove_reference<string> , что просто string
  5. Чего я не понимаю, так это типаamp;amp; . Я уже видел что-то вроде ::type, но я не знаю, имеет ли значение ::typeamp;amp; .
  6. Итак, я преобразую t, тип которого был выведен в string (здесь может быть мое недоразумение), во все это, что кажется справедливым string . Я знаю, что std::move должен возвращать ссылку на значение rvalue независимо от того, передаем ли мы ему значение rvalue или значение lvalue, я просто не могу туда попасть. Может кто-нибудь помочь?

Комментарии:

1. s2 = std::move(string(“hello”)); то же s2 = string(“hello”); самое, что ie std::move , не имеет никакого эффекта.

2. Существует std::remove_reference<std::string> , который является индивидуальным классом, который определяет type . И есть также std::remove_reference_t<std::string> , который действительно является псевдонимом для std::string . en.cppreference.com/w/cpp/types/remove_reference

Ответ №1:

remove_reference<string> это НЕ то же самое, что просто string . Это структура type , в области видимости которой определен typedef string . Так remove_reference<string>::type и есть string .

Таким образом remove_reference<string>::typeamp;amp; stringamp;amp; , является ссылкой rvalue на string

Более короткий способ записи, который был бы remove_reference_t<string>amp;amp; (обратите внимание на _t )

Комментарии:

1. спасибо, человек, очень ясно. Итак, в основном это ::type и ::typeamp;amp; — это просто псевдонимы, и в данном случае это похоже на строку amp;amp; . Я видел нечто подобное и в реализации пользовательского распределителя, где вам нужно точно так же указывать псевдонимы, верно?

2. Да, точно, ::type это просто псевдоним, очень похожий на те, которые предоставляются в распределителях. Только amp;amp; это не часть псевдонима, а скорее дополнительный квалификатор, добавленный к нему.

3. Ах да, конечно, еще раз спасибо, чувак

Ответ №2:

1 ~ 3 верны. Из 4,

remove_reference<string> это …, remove_reference<string> , это не string так. remove_reference<string>::type есть string . Так remove_reference<string>::typeamp;amp; и есть stringamp;amp; , т.Е. rvalue-ссылка на string . Поскольку возвращаемый тип std::move rvalue-reference std::move(...) приводит к xvalue:

Следующие выражения являются выражениями xvalue:

  • вызов функции или перегруженное выражение оператора, возвращаемым типом которого является ссылка rvalue на объект, например std::move(x) ;

В результате std::move(string("hello")) преобразуется значение string("hello") prvalue в значение xvalue, даже если оба значения prvalue и xvalue являются значениями rvalue. std::move предполагается, что он используется для преобразования lvalue в rvalue , поэтому подобное использование не имеет особого смысла.

Комментарии:

1. большое спасибо, чувак, теперь я понял

Ответ №3:

Это не имеет строгого отношения к вопросу, но полезно знать.
Тип t в качестве параметра шаблона выглядит как ссылка на значение rvalue, но может и не быть

 template <typename T>
RetType fn(Tamp;amp; t)
 

Это особый случай, в котором говорится: «Используйте Tamp;amp; или constTamp; по мере необходимости»

Смотрите Здесь лучшее объяснение, чем я когда-либо мог дать

Редактировать: На самом деле, вам нужно знать это, чтобы ответить на часть 6 вашего вопроса.