std::move obtains an rvalue reference to its argument, which converts it to an xvalue.

Code that receives such an xvalue has the opportunity to optimize away unnecessary overhead by moving data out of the argument, leaving it in a valid but unspecified state.

In detail, code that is passed an rvalue (either a prvalue such as a temporary object or an xvalue such as the one produced by std::move) that identifies a resource-owning object has the option (but isn't required) to move the resource out of the argument in order to run more quickly, leaving the argument with a valid but unspecified value. The library code is required to leave a valid value in the argument, but unless the type or function documents otherwise, there are no other constraints on the resulting argument value. This means that it's generally wisest to avoid using a moved-from argument again. If you have to use it again, be sure to re-initialize it with a known value before doing so.