Possible Duplicate:
Move constructor signature
struct X
{
X(X&); // (1)
X(X&&); // (2)
X(const X&); // (3)
X(const X&&); // (4)
};
Are there any situations where (4)
will be picked in overload resolution?
Possible Duplicate:
Move constructor signature
struct X
{
X(X&); // (1)
X(X&&); // (2)
X(const X&); // (3)
X(const X&&); // (4)
};
Are there any situations where (4)
will be picked in overload resolution?
Yes. One situation is when you have a function with a const
return value:
const X f();
X x(f());
Another situation is when you are applying std::move
to a const
object, as in the following example:
#include <iostream>
using namespace std;
struct X
{
X() { cout << "default" << endl; }
X(X&) { cout << "non const copy" << endl; } // (1)
X(X&&) { cout << "non const move" << endl; } // (2)
X(const X&) { cout << "const copy" << endl; } // (3)
X(const X&&){ cout << "const move" << endl; } // (4)
};
void f(X const x)
{
}
int main()
{
X const x;
f(std::move(x));
return 0;
}
The case mentioned in a previous answer (X const f()
) is probably less common, because the move constructor is most of the times elided by the compiler when doing RVO (this can be done even if the constructor has side-effects).
Moving a const
object into another const
object as a logical operation does make sense, and if you do not define a const
move constructor then you won't be allowed to do that. Moving is just transferring ownership, so it seems to me that as a logical operation it should be supported.
Although it is true that from a high-level viewpoint you are not supposed to modify a const
object and indeed moving an object requires modifying it (in most cases), there are well-known similar situations where it is OK to modify a const
object "behind the scenes" for the purpose of realizing a higher-level conceptual operation. Think for instance of a const
member function that needs to lock a non-const member mutex: you may declare the mutex variable as mutable
to treat it as a non-const object.
So even in this case I see it as a legitimate operation in a const
move constructor (as long as it is needed) to modify mutable
members of the moved object (perhaps some boolean flag to be checked by the object's destructor). Please notice, that if you remove the const
constructors (3) and (4) from the code above, then it won't compile. If you remove only (4), the copy constructor (3) will be chosen - meaning you won't be able to move the const
object.