What I want to briefly talk about today is likely obvious to seasoned C++ programmers, but may be of benefit for the newcomers to the language and the STL: that is how to efficiently create
std::vectorof any number of elements of type
T, whatever
Tmay be. The code is short and sweet, so let’s jump right into it:
#includetemplate inline auto make_N_of_T(std::size_t N, A&&... a) { std::vector v; v.reserve(N); for(std::size_t i = 0; i < N; ++i) v.emplace_back(std::forward(a)...); return v; }
In lines #3 and #4 we define the creation function template (
inlinebecause it’s likely to live in a header file and we don’t want to violate the ODR) that says make me N instances of T and use A as parameter(s) to T’s constructor (see parameter packs and fold expressions). Next we create an instance of
std::vector<T>in line #6 and reserve enough space for
Ninstances of
Tin line #7 (without actually constructing instances of
Tyet). Line #8 is self explanatory, and the efficiency magic happens in line #9. Instead of creating a temporary instance of
Tand calling
.push_backwe instead
.emplace_backeach instance of
T, meaning we construct it in the memory previously reserved for the elements of the container in line #7. This way we avoid unnecessary copy or move constructors (which may not even be defined for type
T).
Before C++11 and move semantics we would have been stuck with creating an instance of
T, then copy constructing it into every element of
std::vector<T>, like this:
std::size_t N = 42; vectorv(N, T{});
And don’t even get me started on having to return
std::vector<T>from a function and how costly that would have been (again, prior to the magic of move semantics)! We’re in a brave new world…
P.S. I hope you’re all doing well and staying safe in this COVID-19 world! The situation has certainly put a strain on me and a dent in my blogging frequency. I hope to return to my normal post-or-more-a-week blogging frequency soon!