vukung vukung - 2 months ago 17
C++ Question

Efficient direct initialization of a std::vector

I have a struct, say

struct A {
A(int n) : n(n) {}
int n;
};


and I want to initialize a
std::vector
with some elements. I can do this by using an initialization list, or by emplacing the new elements:

// 1st version: 3 ctors, 3 copy ctors, 3 dtors
std::vector<A> v1{1, 2, 3};

// 2nd version: 3 ctors
std::vector<A> v2;
v2.reserve(3);
v2.emplace_back(4);
v2.emplace_back(5);
v2.emplace_back(6);


As the comments show, the first version calls 3 constructors, 3 copy constructors, and 3 destructors. The version with emplace only uses 3 constructors.

Question: Obviously the second version is better, but the first version is more succinct. Can I have the best of both worlds? Can I do a direct initialization without the extra cost?

(Here's a longer version of the
A
struct that shows what's happening.)

Answer

Since A is convertible from int, you can use the range constructor of vector:

auto inits = {1, 2, 3};
std::vector<A> v1{std::begin(inits), std::end(inits)};

Or in a single declaration-statement (assuming you can rely on RVO):

auto v1 = [inits={1, 2, 3}] { return std::vector<A>{std::begin(inits), std::end(inits)}; }();