C++ std::move
Jun 16, 2021 at 16:58
std::move
It’s really just a cast to T&&
Some code
#include <iostream>
#include <string>
class Widget {
public:
Widget() = default;
void set(const std::string & name_) {
std::cout << "const ref " << name_ << std::endl;
name = name_;
std::cout << "const ref " << name << std::endl;
}
void set(std::string && name_) {
std::cout << "r-ref " << name_ << std::endl;
name = std::move(name_);
std::cout << "r-ref " << name << std::endl;
}
private:
std::string name;
};
int main() {
auto w = Widget{};
w.set(std::string{"first"});
std::string other { "other"};
w.set(other);
w.set(std::move(other));
std::cout << "Other = '" << other << "'\n";
return 0;
}
Output:
r-ref first
r-ref first
const ref other
const ref other
r-ref other
r-ref other
Other = ''
Observations
If I change the second set
method to:
void set(std::string && name_) {
std::cout << "r-ref " << name_ << std::endl;
name = name_;
std::cout << "r-ref " << name << std::endl;
}
we get:
r-ref first
r-ref first
const ref other
const ref other
r-ref other
r-ref other
Other = 'other'
If we make other
const:
int main() {
auto w = Widget{};
w.set(std::string{"first"});
const std::string other { "other"};
w.set(other);
w.set(std::move(other));
std::cout << "Other = '" << other << "'\n";
return 0;
}
we get:
r-ref first
r-ref first
const ref other
const ref other
const ref other
const ref other
Other = 'other'
and clang-tidy
, if installed, warns:
Clang-Tidy: Std::move of the const variable ‘other’ has no effect; remove std::move() or make the variable non-const
because, under standard C++ lookup rules, it cannot find a method with the signature void set(const std::string&& name_);
so it defers to the const reference version,
but if we add such a method:
void set(const std::string && name_) {
std::cout << "const r-ref " << name_ << std::endl;
name = std::move(name_);
std::cout << "const r-ref " << name << std::endl;
}
Which works, sort of:
r-ref first
r-ref first
const ref other
const ref other
const r-ref other
const r-ref other
Other = 'other'
Note the last line, other
has not been moved by std::string
. That’s because std::string
does not have any members that take a const T&&
.
In fact, moving implies modification, so it makes little sense to create methods that take const T&&
.
More links here: