Этот код имеет четко определенное поведение.
В C ++ 17, std::move(p)
будет оцениваться до m[p->s]
. До C ++ 17 std::move(p)
можно было оценить до или после m[p->s]
. Однако это не имеет значения, потому что std::move(p)
не изменяет p
. Только присвоение фактически приводит к перемещению p
из.
Вызываемый оператор присваивания имеет сигнатуру
unique_ptr& operator=(unique_ptr&& other);
и вызывается так, как если бы он был
m[p->s].operator=(std::move(p));
Это означает, что изменение p
гарантированно не произойдет, пока не будет введено тело из operator=
(инициализация параметра other
является просто привязкой ссылки ). И, конечно, тело operator=
не может быть введено до тех пор, пока не будет оценено выражение m[p->s]
.
Таким образом, ваш код четко определен во всех версиях C ++.