I was reading Effective Modern C++ Item 25, on page 172, it has an example to demonstrate that, if you want to move return an rvalue reference parameter, you need to wrap it with std::move(param). As parameter by itself is always an lvalue, if no std::move(), it will be copy returned.
I don't understand. If std::move(param) merely cast the parameter it takes in into an rvalue reference, then what's the difference when param is already an rvalue reference?
Like in the code below:
#include <string>
#include <iostream>
#include <utility>
template<typename T>
class TD;
class Widget {
public:
explicit Widget(const std::string& name) : name(name) {
std::cout << "Widget created with name: " << name << ".\n";
}
Widget(const Widget& w) : name(w.name) {
std::cout << "Widget " << name << " just got copied.\n";
}
Widget(Widget&& w) : name(std::move(w.name)) {
std::cout << "Widget " << name << " just got moved.\n";
}
private:
std::string name;
};
Widget passThroughMove(Widget&& w) {
// TD<decltype(w)> wType;
// TD<decltype(std::move(w))> mwType;
return std::move(w);
}
Widget passThrough(Widget&& w) {
return w;
}
int main() {
Widget w1("w1");
Widget w2("w2");
Widget wt1 = passThroughMove(std::move(w1));
Widget wt2 = passThrough(std::move(w2));
return 0;
}
It outputs:
Widget created with name: w1.
Widget created with name: w2.
Widget w1 just got moved.
Widget w2 just got copied.
In passThroughMove(Widget&& w), w's type is already rvalue reference, std::move(w) just cast it into rvalue reference again. If I uncomment the TD lines, I can see that of decltype(w) and decltype(std::move(w)) are both Widget &&:
move_parameter.cpp:27:21: error: implicit instantiation of undefined template 'TD<Widget &&>'
TD<decltype(w)> wType;
^
move_parameter.cpp:28:32: error: implicit instantiation of undefined template 'TD<Widget &&>'
TD<decltype(std::move(w))> mwType;
^
As both w and std::move(w) are same rvalue reference type, why "return std::move(w)" moves w, while "return w" only copy?
Aucun commentaire:
Enregistrer un commentaire