问题
I tested c++11 move function, but not become effective. Who can tell me why ? Thanks. The code is as follows:
class Base {
public:
Base() { cout << "Base" << endl;}
~Base() { cout << "~Base" << endl;}
Base(const Base& base) { cout << "Copy" << endl; }
Base& operator=(const Base& base) {cout << "operator=" << endl;}
Base(Base&& base) { cout << "move" << endl;}
Base& operator=(Base&& base) { cout << "move=" << endl;}
};
Base b;
Base&& GetResult() {
return std::move(b);
}
int main() {
Base&& tmp = GetResult();
cout << &b << endl;
cout << &tmp << endl;
}
Output:
Base
0x6013a0
0x6013a0
~Base
Why move copy
and move operator=
not be called ? And why address is the same ?
回答1:
To add to the excellent existing answers, I believe the main point of confusion here is what std::move
does.
std::move
does not move.
It was abysmally named.
It only gives you an xvalue referring to whatever you gave it; this xvalue will bind to a rvalue reference where an lvalue won't. This means the result of std::move
can be given to a move constructor or move assignment operator. However, it does not do that for you, and you do not do it here.
Given such strong criticism for the naming, surely you have an alternative suggestion
– user2079303
This is a well-trodden topic, but the creator of C++ suggests std::rval, and one of the architects of modern C++ suggests std::rvalue_cast (even though you actually get an xvalue).
Personally, I think std::moveable
would have been a nice middle ground.
回答2:
Why move copy and move operator= not be called ?
I assume that by "move copy" you mean "move constructor". Move assignment operator is not called, because you never use the assignment operator.
There are no moves (nor copies) because Base&&
is a reference (an r-value reference to be specific). References refer / point to an object - they do not contain state of the object. When you initialize a reference, no object is copied or moved.
And why address is the same ?
When the address-of operator is applied to a reference, you get the address of the referred object.
回答3:
Let's ignore move semantics for a minute, and only think about familiar, C++98 copy constructors. Given the following code, what output would you expect?
class Base {
public:
Base() { cout << "Base" << endl;}
~Base() { cout << "~Base" << endl;}
Base(const Base& base) { cout << "Copy" << endl; }
Base& operator=(const Base& base) {cout << "operator=" << endl;}
};
Base b;
Base& GetResult() {
return b;
}
int main() {
Base& tmp = GetResult();
cout << &b << endl;
cout << &tmp << endl;
}
Of course, you would expect a call to the Base
default constructor, followed by the address of b
printed twice, followed by the Base
destructor. The reason is because you're only constructing one Base
instance, and never copying it -- you're only using references.
So it is with your example. You're using rvalue references rather than lvalue references, but the point is the same -- there is only ever one Base
variable, and no copying or moving ever happens. If you want to witness move semantics in action, you could try something like this:
Base getBase() {
return Base{};
}
int main() {
Base tmp = getBase();
Base other = std::move(tmp);
}
(The move out of getBase()
will probably be optimised out by the compiler, but you should still see the second one.)
来源:https://stackoverflow.com/questions/43523753/c11-move-not-take-effective