Reputation: 10562
Why doesn't this: (vs2010) move the vector within the class?
#include <vector>
class MoveTest
{
public:
std::vector<int> m_things;
};
int _tmain(int argc, _TCHAR* argv[])
{
MoveTest m;
m.m_things.push_back(12);
MoveTest m2 = std::move(m);
// std::vector has been copied, not moved
return 0;
}
Does this mean every class that uses std::vector (and other moveable classes) should have an explicit move constructor and assignment?
Upvotes: 3
Views: 1357
Reputation: 218830
In addition to the good answers already given regarding the lateness of these rules compared to when vs2010 shipped,
The rules for an implicitly generated move constructor are:
If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
- X does not have a user-declared copy constructor,
- X does not have a user-declared copy assignment operator,
- X does not have a user-declared move assignment operator,
- X does not have a user-declared destructor, and
- the move constructor would not be implicitly defined as deleted.
The rules for implicitly generated move assignment operators follows the pattern above.
The rules for when a copy constructor is implicitly generated have changed slightly!
If the class definition does not explicitly declare a copy constructor, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.
And similarly for the copy assignment operator:
If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if the class has a user-declared copy constructor or a user-declared destructor.
Bottom line: The rule of 3 is now the rule of 5. You can either ignore all 5 (if the default behavior works for you), or you need to think about (and likely define) all 5:
Upvotes: 9
Reputation: 68611
With a fully-conforming C++0x compiler, your class will have an implicit move constructor that moves the members, as well as the implicit copy constructor. In this example, the implicit move constructor will therefore be used.
However, MSVC2010 came out before this rule was agreed on by the committee, so you must write a move constructor explicitly. You will then need to define the default constructor and copy constructor as well, and probably ought to define the move-assignment and copy-assignment too for good measure:
class MoveTest
{
public:
std::vector<int> m_things;
MoveTest()
{}
MoveTest(MoveTest&& other):
m_things(std::move(other.m_things))
{}
MoveTest(MoveTest const& other):
m_things(other.m_things)
{}
MoveTest& operator=(MoveTest&& other)
{
MoveTest temp(std::move(other));
std::swap(*this,temp);
return *this;
}
MoveTest& operator=(MoveTest const& other)
{
if(&other!=this)
{
MoveTest temp(other);
std::swap(*this,temp);
}
return *this;
}
};
Upvotes: 7
Reputation: 146940
VS2010 does not have implicit move constructors. You will have to explicitly write one.
Upvotes: 1
Reputation: 92271
The MoveTest
class doesn't have a move constructor, so it used the default copy constructor.
A copy constructor copies the member elements. :-)
There might be cases where a C++11 conformat compiler would generate a default move constructor, but I'm not sure where the final rules ended up (there were very late changes). VS2010 is too old to know about that as well.
Upvotes: 2