Consider below code:
#include <iostream>
#include <vector>
struct C {
C() {}
C(const C&) { std::cout << "A copy was made.\n"; }
C(C&&) {std::cout << "A move was made.\n";}
};
std::vector<C> g() {
std::vector<C> ret {C(), C(), C()};
return ret;
}
std::vector<C> h() {
std::vector<C> ret;
ret.reserve(3);
ret.push_back(C());
ret.push_back(C());
ret.push_back(C());
return ret;
}
int main() {
std::cout << "Test g\n";
std::vector<C> v1 = g();
std::cout << "Test h\n";
std::vector<C> v2 = h();
}
Compiled with g++ -std=c++11 main.cpp && ./a.out
, the result is:
Test g
A copy was made.
A copy was made.
A copy was made.
Test h
A move was made.
A move was made.
A move was made.
Note that both functions uses copy elision so the returned std::vector<C>
is not copied.
I understand why h()
uses move-constructor
, but why g()
uses copy-constructor
?
From vector's doc:
(6) initializer list constructor
Constructs a container with a copy of each of the elements in il, in the same order.
It looks like initializer-list always copy the elements, then probably it mean the initializer-list constructor
's performance could be impacted if C
is cheap to move but heavy to copy.
So my question: what is the preferred way to initialize a container (e.g. vector
) with objects that are cheap to move but heavy to copy?