Допустима ли перемещенная переменная для использования после std::move?

#c #move

#c #переместить

Вопрос:

Мне трудно понять, если я std::move переключаюсь с одной переменной на другую, по-прежнему ли допустима исходная переменная для использования или она действует как висячий указатель? она по-прежнему указывает на память стека?

например:

 int a = 5;
int b = std::move(a) // b owns a resources now

a = 10 // is this valid? does it have memory address?
std::cout << a; // prints 10 obviously valid?
  

Ответ №1:

Обратите внимание, что std::move не перемещает свой аргумент, он просто приводит его к ссылке rvalue. Что на самом деле перемещает объект, так это конструктор или оператор присваивания, которые принимают ссылку rvalue .

Но int это встроенный тип и у него нет такого конструктора или operator= , поэтому применение std::move к int не приведет к его перемещению.

Оставляя встроенные типы в стороне, стандарт C гласит, что перемещаемый объект должен находиться в допустимом, но неуказанном состоянии. Обычно это означает, что мы не можем использовать ее значение, но можем повторно присвоить его.

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

1. Этот последний бит также является требованием для типов std: вы можете без проблем вызывать функции без предварительных условий (хотя вызов size для вектора moved from все равно будет неуказанным, даже если это не вызовет неопределенного поведения). Для интеллектуальных указателей Moved из std также устанавливается значение nullptr, что является еще одной дополнительной функцией, определенной в стандарте.

Ответ №2:

std::move ничего не делает с модулем.

 int a = 5;
int b = std::move(a);
  

a после этого все еще работает.

Для типов, отличных от POD, перемещаемый объект может быть допустимым для одних операций и недопустимым для других операций — все зависит от того, что делает конструктор перемещения или оператор присваивания перемещения.

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

1. Возможно, вам следует расширить ответ, включив поведение для типов, отличных от POD.

2. @CinCout, поведение для типов, отличных от POD, настолько сильно зависит от конструктора move, что о них трудно сказать что-либо полезное.

3. итак, является ли единственной целью std::move вызов move asignment и move consturctos? есть какой-либо другой случай, помимо этих двух понятий?

4. @zebanovich Семантика перемещения никоим образом не ограничена. Любая функция может использовать больше из любого аргумента.

5. @zebanovich, это все, о чем я могу думать.

Ответ №3:

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