I\'m writing a app for both linux & windows, and noticed that the GCC build is producing a lot of useless calls to the copy constructor.
Here\'s an example code
Try this then:
std::vector<A> vec_a;
vec_a.reserve(3);
for (size_t i = 0; i < 3; ++i)
vec_a.push_back(A());
What you're trying to do is force the initialization process to use construct+move for each value instead of construct and then copy/copy/copy. These are just different philosophies; the libraries authors couldn't possibly know which is going to be the best for any given type.
You can add special (cheap) case to copy ctor algorithm when copying default constructed object to "this" object. It's just a workaround, however, the behaviour is strange enough. Both compilers (libraries) create a temporary object on the stack, then gcc copies this temporary to the targets 3 times; msvc recreates temporary object 3 times (!) (on the stack too) and moves 3 timesn to targets. I don't understand why they don't create objects directly in place.
Looks like the problem is that the version of g++ that you have does not have a C++0x fully compliant library. In particular, in C++03, the size constructor of std::vector has the following signature:
// C++ 03
explicit vector(size_type n, const T& value = T(),
const Allocator& = Allocator());
With that function signature and your call, a temporary is created, then bound by the constant reference and copies of it are created for each one of the elements.
while in C++0x there are different constructors:
// C++0x
explicit vector(size_type n);
vector(size_type n, const T& value, const Allocator& = Allocator());
In this case, your call will match the first signature, and the elements should be default constructed with placement new over the container (as @Howard Hinnant correctly points out in his answer the compiler should not call the move constructor at all).
You can try and check if more recent versions of g++ have an updated standard library, or you can work around the issue by manually adding the elements:
std::vector<A> v;
v.reserve( 3 ); // avoid multiple relocations
while (v.size() < 3 ) v.push_back( A() );
Both implementations (Visual C++ 2010 and GCC 4.4.0) are in error. The correct output is:
default
default
default
This is specified in 23.3.5.1 [vector.cons]/4:
Requires: T shall be DefaultConstructible.
The implementation is not allowed to assume that A is either MoveConstructible nor CopyConstructible.
I think, that all 3 variants do not violate C++0x draft. It requires following: 1. Constructs a vector with n value-initialized elements 2. T shall be DefaultConstructible 3. Linear in n
All 3 variants satisfy 1, as default + copy, default + move are equivalent to default All 3 variants satisfy 3 All 3 variants satisfy 2: they work for DefaultConstructible types. Specific algorithm can be used for Moveable types. It is a general practice in STL to use different versions of algorithms for types with different capabilities.