bar
- это rvalue или lvalue?
Ответ на вопрос сам собой. Все, что имеет имя, имеет lvalue (1). Итак, bar
- это lvalue. Его тип - "ссылка rvalue на string
", но это lvalue этого типа.
Если вы хотите рассматривать его как rvalue, вам нужно применить к нему std::move()
.
Если вы можете выполнить любую операцию со ссылкой rvalue, которую вы можете выполнить со ссылкой lvalue, то какой смысл различать их с помощью «&&», а не просто «&»?
Это зависит от вашего определения «выполнить операцию». Ссылка lvalue и (именованная) ссылка rvalue в значительной степени идентичны в том, как вы можете использовать их в выражениях, но они различаются во многом тем, что может связываться с ними. Lvalues могут связываться со ссылками lvalue, rvalue могут связываться со ссылками rvalue (и все может связываться со ссылкой lvalue на const
). То есть вы не можете привязать rvalue к ссылке lvalue или наоборот.
Давайте поговорим о параметре функции ссылочного типа rvalue (например, о вашем bar
). Важно не то, что такое bar
, а то, что вы знаете о значении, к которому относится bar
. Поскольку bar
является ссылкой rvalue, вы наверняка знаете, что все, что с ней связано, было rvalue. Это означает, что оно обязательно будет уничтожено, когда закончится полное выражение, и вы можете безопасно рассматривать его как rvalue ( путем кражи его ресурсов и т. д.).
Если не вы делаете это напрямую с bar
, а просто хотите передать bar
, у вас есть два варианта: либо вы закончили с bar
, а затем вы должны сообщить следующему, кто его получит, что он привязан к rvaluedo std::move(bar)
. Или вам нужно будет сделать еще кое-что с bar
, и поэтому вы не хотите, чтобы кто-либо в промежутке крал его ресурсы из-под вас, поэтому просто рассматривайте это как lvaluebar
.
Подводя итог: Разница не в том, что вы можете делать со ссылкой , когда она у вас есть. Разница в том, что можно привязать к ссылке. сильный>
(1) Хорошее практическое правило с небольшими исключениями: у счетчиков есть имена, но они являются r-значениями. Классы, пространства имен и шаблоны классов имеют имена, но не значения.
person
Angew is no longer proud of SO
schedule
12.02.2015
string temp1(bar), temp2(bar);
- person Jonathan Mee   schedule 12.02.2015bar
является lvalue (его тип - rvalue, странно, что я знаю). Однако если вы дважды позвонилиstd::move
, у вас могут возникнуть проблемы. - person Guvante   schedule 12.02.2015bar
именно объясняет, почемуbar
является lvalue - чтобы такое двойное использование не доставляло вам проблем. Он обрабатывается как rvalue только тогда, когда вы делаете это явно:std::move(bar)
. - person Angew is no longer proud of SO   schedule 12.02.2015move
? Я просто не понимаю. Тогда почему мы вообще называем это ссылкой на rvalue? Единственное, что я думал, это требовало построения хода. Но если даже этого не сделать ... - person Jonathan Mee   schedule 12.02.2015bar
, будет уничтожена, это то, что вы получите. Однако, если вы затем вызываете функцию внутри себя, вы не даете этой гарантии, если вы явно не говорите об этом. - person Guvante   schedule 12.02.2015std::move
или аналогичного), поэтому ваша функция может предположить, что можно перейти от нее. - person Mike Seymour   schedule 12.02.2015static_cast<int&&>(42)
по-прежнему является выражением-rvalue, тогда как letint x = 42;
thenstatic_cast<int&>(42)
является выражением lvalue. - person dyp   schedule 12.02.2015