С одной стороны,
string&& s2 = std::move(s1);
вовсе не является заданием;это инициализация.
И это инициализация ссылки, а не объекта.В вашей программе есть только один std::string
с именем s1
.Поскольку вы объявили s2
как ссылку, она ссылается на какой-то другой объект - здесь это s1
.Так что никакой конструктор перемещения или оператор присваивания перемещения вообще не нужно вызывать, и s1
нельзя изменить.
Если вы вместо этого напишите
string s2 = std::move(s1);
, это фактически создаствторой std::string
объект с именем s2
.Он инициализируется с помощью конструктора перемещения.
Или, если =
используется на ранее объявленном объекте, чтобы не вводить инициализатор сразу после объявления, тогда это истинное присваивание:
string s2;
s2 = std::move(s1);
Здесь s2
сначала создается с помощью конструктора std::string
по умолчанию, а затем изменяется с помощью std::string
оператора присваивания перемещения.
Но обратите внимание, что после std::string
конструктор перемещения или оператор присваивания перемещениясодержимое объекта «отъехал» не указано .В некоторых случаях Стандарт говорит точно, что будет делать операция перемещения, часто делая перемещенный объект пустым.Но если не указано иное, он говорит только о том, что объект находится в «допустимом, но неопределенном состоянии».И std::string
не добавляет никаких особых требований, поэтому результатом является неопределенное состояние.Поэтому печать s1
после этого может привести к чему-либо.(Практически говоря, если в реализации std::string
используется оптимизация малых строк, вы можете обнаружить, что s1
не был изменен.)