So even if it takes a reference, if the type doesn't match, it needs to copy construct anyway? |
That's often true, but it depends on what constructors there are.
But in this case it wouldn't matter whatever constructor std::string had because you're passing a
pointer. Even if the pointer is an rvalue it doesn't give permission to move (e.g. "modify" or "steal" from) the object that the pointer points to because the rvalue-ness only refers to the pointer itself.
Does this mean passing a const char* into a function that takes const std::string& would be just as expensive as passing a std::string by value? |
Basically, yes. The char data would have to be copied in both cases.
But if you already have a std::string object then the const std::string& version would be less expensive because it doesn't have to copy anything.
I thought that std::move() was just the same as static_cast<std::string&&>() here, and that's what arg aleady was at that point. |
That's the "declared type" but it's not the type of the expression when you use the variable name.
You might want to use the variable more than once and you might not want to move it the first time.
Example:
1 2 3 4 5 6 7
|
std::vector<T> vec;
T last_value{};
void add(T&& x) {
vec.push_back(x);
last_value = std::move(x);
}
|
It would be surprising if
vec.push_back(x)
modified
x (it means
last_value would not receive the intended value). That's why you need to be explicit when moving from variables (except when using
return or
throw). It would be too easy to write buggy code otherwise.