Move, std::vector and gcc: which is this correct?
I have a simple program below which defines or defaults various
combinations of move and copy constructors and puts the classes into a
std::vector.
#include <iostream>
#include <vector>
using namespace std;
struct Both
{
Both() = default;
Both(Both&&)
{
cout << "Move\n";
}
Both(const Both&)
{
cout << "Copy\n";
}
};
struct MoveOnly
{
MoveOnly() = default;
MoveOnly(MoveOnly&&)
{
cout << "Move\n";
}
};
struct DefaultMove
{
DefaultMove() = default;
DefaultMove(DefaultMove&&)=default;
DefaultMove(const DefaultMove&)
{
cout << "Copy\n";
}
};
template<class C> void test()
{
vector<C> f;
for(int i=0; i < 5; i++)
{
cout << "Iteration " << i;
if(f.capacity() <= i)
cout << " resize expected";
cout << endl;
f.push_back({});
cout << endl;
}
};
int main()
{
cout << "------------------------Both:\n";
test<Both>();
cout << "-----------------------MoveOnly:\n";
test<MoveOnly>();
cout << "-----------------------DefaultMove:\n";
test<DefaultMove>();
}
With gcc 4.6, I get the following output:
------------------------Both:
Iteration 0 resize expected
Move
Iteration 1 resize expected
Move
Move
Iteration 2 resize expected
Move
Move
Move
Iteration 3
Move
Iteration 4 resize expected
Move
Move
Move
Move
Move
-----------------------MoveOnly:
Iteration 0 resize expected
Move
Iteration 1 resize expected
Move
Move
Iteration 2 resize expected
Move
Move
Move
Iteration 3
Move
Iteration 4 resize expected
Move
Move
Move
Move
Move
-----------------------DefaultMove:
Iteration 0 resize expected
Iteration 1 resize expected
Iteration 2 resize expected
Iteration 3
Iteration 4 resize expected
This is what I expected. When the vector resizes itself, the move
constructor is always called. In the final case, this is implied by the
copy constructor not being called.
However, with 4.7, I get:
------------------------Both:
Iteration 0 resize expected
Move
Iteration 1 resize expected
Move
Copy
Iteration 2 resize expected
Move
Copy
Copy
Iteration 3
Move
Iteration 4 resize expected
Move
Copy
Copy
Copy
Copy
-----------------------MoveOnly:
Iteration 0 resize expected
Move
Iteration 1 resize expected
Move
Move
Iteration 2 resize expected
Move
Move
Move
Iteration 3
Move
Iteration 4 resize expected
Move
Move
Move
Move
Move
-----------------------DefaultMove:
Iteration 0 resize expected
Iteration 1 resize expected
Iteration 2 resize expected
Iteration 3
Iteration 4 resize expected
In other words, when both copy and move are defined explicitly, the copy
constructor gets called but if the move constructor is defaulted, then it
gets called in preference to the copy constructor.
I would have expected the GCC 4.6 behaviour to be correct. Am I mistaken?
-Ed
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]