Most developers have no trouble getting the idea of C++'s function overloading for parameter types that are totally different, e.g. it's clear what foo("xyz") will call if you have:
void foo(int x);
void foo(std::string x);
It's also not too hard to get the idea with const and mutable references: void foo(std::string& x);
void foo(const std::string& x);
Rvalue references allow another possibility: void foo(std::string&& x);
void foo(const std::string& x);
(Technically it's also possible to overload with rvalue and non-const regular references, or even all three, but this is rarely done in practice).In this pairing, the first option would be chosen for a temporary object (e.g. foo(std::string("xyz")) or just foo("xyz")), while the second would be chosen if passing in a named variable (std::string x; foo(x)). In practice, the reason you bother to do this is so the the first overload can pilfer memory resources from its argument (whereas, presumably, the second will need to do a copy).
The point of std::move() is to choose the first overload. This has the consequence that its argument will probably end up being modified (by foo()) even though std::move() itself does not contain any substantial code.
All of the above applies to constructors, since they are functions and they can also be overloaded. Therefore, the following function is very similar in most practical situations since std::string has overloaded copy and move constructors:
void foo(std::string x);