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::vector of any number of elements of type T, whatever T may be. The code is short and sweet, so let’s jump right into it:

In lines #3 and #4 we define the creation function template ( inline because 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 N instances of T in line #7 (without actually constructing instances of T yet). Line #8 is self explanatory, and the efficiency magic happens in line #9. Instead of creating a temporary instance of T and calling .push_back we instead .emplace_back each 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:

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!

2 Replies to “Make std::vector of T, efficiently”

  1. Templates are exceptions to ODR rule so inline is not required there:
    C++11 3.2/5:

    If D is a template and is defined in more than one translation unit, then the preceding requirements shall apply both to names from the template’s enclosing scope used in the template definition (14.6.3), and also to dependent names at the point of instantiation (14.6.2). If the definitions of D satisfy all these requirements, then the program shall behave as if there were a single definition of D. If the definitions of D do not satisfy these requirements, then the behavior is undefined.

    [C++14: 3.2/6]: There can be more than one definition of a class type (Clause 9), enumeration type (7.2), inline function with external linkage (7.1.2), class template (Clause 14), non-static function template (14.5.6), static data member of a class template (14.5.1.3), member function of a class template (14.5.1.1), or template specialization for which some template parameters are not specified (14.7, 14.5.5) in a program provided that each definition appears in a different translation unit, and provided the definitions satisfy the following requirements [..]

Leave a Reply