Почему вы используете std:: move, когда у вас есть && в C++11? [дубликат]
Возможные Дубликаты:
может кто-нибудь объяснить мне семантику перемещения?
недавно я присутствовал на семинаре C++11, и был дан следующий лакомый кусочек совета.
when you have && and you are unsure, you will almost always use std::move
может ли кто-нибудь объяснить мне, почему вы должны использовать std::move в отличие от некоторых альтернатив, а в некоторых случаях, когда вы не должны использовать std::move?
4 ответов:
во-первых, есть, вероятно, неправильное представление в вопросе, который я рассмотрю:
Всякий раз, когда вы видитеT&& tв коде (и T-это тип, а не тип шаблона), имейте в виду категорию, стоимостьюtявляется lvalue (ссылка), а не rvalue(временный) больше. Это очень запутанно. ЭлементT&&означает, чтоtи построен от объекта, который был rvalue 1, аtявляется lvalue, а не rvalue. Если это имеет имя (в данном случае,t) тогда это значение lvalue и не будет автоматически перемещаться, но если у него нет имени (результат3+4) тогда это rvalue и будет автоматически перейти в его результат, если это возможно. Элемент тип (в данном случаеT&&) не имеет почти никакого отношения к категории значений переменной (в данном случае lvalue).это, как говорится, если у вас есть
T&& tнаписано в коде, это означает, что у вас есть ссылка на переменную это был временное, и это нормально, чтобы уничтожить, если вы хотите. Если вам нужно получить доступ к переменной несколько раз, вы делаете не хотитеstd::moveот него, иначе он потеряет свою ценность. Но в последний раз вы его не видели!--1--> безопасноstd::moveэто значение для другогоTесли вы хотите. (А 95% времени, это то, что вы хотите сделать). Все это также относится кauto&&переменные.1. если
Tтип шаблона ,T&&вместо этого является ссылкой для пересылки, и в этом случае вы используетеstd::forward<T>(t)вместоstd::move(t)в последний раз. Смотрите этот вопрос.
нашел в этой статье чтобы быть довольно информативным по вопросу ссылок на rvalue в целом. Он упоминает
std::moveк концу. Это, пожалуй, самая актуальная цитата:мы должны использовать
std::moveС<utility>--std::move- это способ говоря: "хорошо, честное слово, я знаю, что у меня есть lvalue, но я хочу этого быть собой rvalue."std::moveсам по себе ничего не перемещает; он просто превращает lvalue в rvalue, так что вы можете вызвать перемещение конструктор.
скажем, у вас есть конструктор перемещения, который выглядит так:
MyClass::MyClass(MyClass&& other): myMember(other.myMember) { // Whatever else. }при использовании оператора
other.myMember, возвращаемое значение является значением lvalue. Таким образом, код использует скопировать конструктор для инициализацииthis->myMember. Но так как это конструктор перемещения, мы знаем, чтоotherявляется временным объектом, а следовательно, и его членами. Так что мы действительно хотим использовать более эффективным!--26-->движение конструктор для инициализацииthis->myMember. Используяstd::moveгарантирует, что компилятор обрабатываетother.myMemberкак ссылка rvalue и вызывает конструктор перемещения, как вы бы хотели:MyClass::MyClass(MyClass&& other): myMember(std::move(other.myMember)) { // Whatever else. }просто не использовать
std::moveна объектах, которые вам нужно держать вокруг - перемещение конструкторов почти гарантированно испортить любые объекты, переданные в них. Вот почему они используются только с временными.надеюсь, что это поможет!
когда у вас есть объект типа
T&&, rvalue, это означает, что этот объект безопасен для перемещения, так как никто другой не будет зависеть от его внутреннего состояния позже.как переезд не должен быть дороже, чем копирование, вы почти всегда хотите, чтобы переместить его. И, чтобы переместить его, вы должны использовать .
когда следует избегать
std::move, даже если это будет безопасно? Я бы не использовал его в тривиальных примерах, например:int x = 0; int y = std::move(x);рядом с этим, я вижу никаких минусов. Если это не усложняет код, то перемещение следует делать по возможности ИМХО.
другой пример, где вы не хотите, чтобы переместить возвращаемые значения. Язык гарантирует, что возвращаемые значения (по крайней мере), что вы не должны писать
return std::move(x); // not recommended(Если Вам ПОВЕЗЕТ, оптимизация возвращаемого значения хиты, что даже лучше, чем операция перемещения.)
вы можете использовать move, когда вам нужно "перенести" содержимое объекта в другое место, не делая копию. Кроме того, объект может принимать содержимое временного объекта без копирования с помощью std::move.
Comments