#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"));
- конструктор для строки hello вернет значение rvalue .
- правила вывода типа говорят нам, что если я передаю rvalue параметруamp;amp;, то
string
в этом случае я получаю указанный тип. - Теперь идет часть static_cast
remove_reference<T>
будет простоremove_reference<string>
, что простоstring
- Чего я не понимаю, так это типаamp;amp; . Я уже видел что-то вроде ::type, но я не знаю, имеет ли значение ::typeamp;amp; .
- Итак, я преобразую t, тип которого был выведен в string (здесь может быть мое недоразумение), во все это, что кажется справедливым
string
. Я знаю, что std::move должен возвращать ссылку на значение rvalue независимо от того, передаем ли мы ему значение rvalue или значение lvalue, я просто не могу туда попасть. Может кто-нибудь помочь?
Комментарии:
1.
s2 = std::move(string(“hello”));
то жеs2 = string(“hello”);
самое, что iestd::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 вашего вопроса.