What is the easiest way to initialize a std::vector with hardcoded elements?

973,706

Solution 1

One method would be to use the array to initialize the vector

static const int arr[] = {16,2,77,29};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );

Solution 2

If your compiler supports C++11, you can simply do:

std::vector<int> v = {1, 2, 3, 4};

This is available in GCC as of version 4.4. Unfortunately, VC++ 2010 seems to be lagging behind in this respect.

Alternatively, the Boost.Assign library uses non-macro magic to allow the following:

#include <boost/assign/list_of.hpp>
...
std::vector<int> v = boost::assign::list_of(1)(2)(3)(4);

Or:

#include <boost/assign/std/vector.hpp>
using namespace boost::assign;
...
std::vector<int> v;
v += 1, 2, 3, 4;

But keep in mind that this has some overhead (basically, list_of constructs a std::deque under the hood) so for performance-critical code you'd be better off doing as Yacoby says.

Solution 3

If you can, use the modern C++[11,14,17,20,...] way:

std::vector<int> ints = {10, 20, 30};

The old way of looping over a variable-length array or using sizeof() is truly terrible on the eyes and completely unnecessary in terms of mental overhead. Yuck.

Solution 4

In C++0x you will be able to do it in the same way that you did with an array, but not in the current standard.

With only language support you can use:

int tmp[] = { 10, 20, 30 };
std::vector<int> v( tmp, tmp+3 ); // use some utility to avoid hardcoding the size here

If you can add other libraries you could try boost::assignment:

vector<int> v = list_of(10)(20)(30);

To avoid hardcoding the size of an array:

// option 1, typesafe, not a compile time constant
template <typename T, std::size_t N>
inline std::size_t size_of_array( T (&)[N] ) {
   return N;
}
// option 2, not typesafe, compile time constant
#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))

// option 3, typesafe, compile time constant
template <typename T, std::size_t N>
char (&sizeof_array( T(&)[N] ))[N];    // declared, undefined
#define ARRAY_SIZE(x) sizeof(sizeof_array(x))

Solution 5

In C++11:

#include <vector>
using std::vector;
...
vector<int> vec1 { 10, 20, 30 };
// or
vector<int> vec2 = { 10, 20, 30 };

Using Boost list_of:

#include <vector>
#include <boost/assign/list_of.hpp>
using std::vector;
...
vector<int> vec = boost::assign::list_of(10)(20)(30);

Using Boost assign:

#include <vector>
#include <boost/assign/std/vector.hpp>
using std::vector;
...
vector<int> vec;
vec += 10, 20, 30;

Conventional STL:

#include <vector>
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, arr + sizeof(arr) / sizeof(arr[0]) );

Conventional STL with generic macros:

#include <vector>
#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof(ar[0])
#define ARRAY_END(ar) (ar + ARRAY_SIZE(ar))
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec (arr, ARRAY_END(arr));

Conventional STL with a vector initializer macro:

#include <vector>
#define INIT_FROM_ARRAY(ar) (ar, ar + sizeof(ar) / sizeof(ar[0])
using std::vector;
...
static const int arr[] = {10,20,30};
vector<int> vec INIT_FROM_ARRAY(arr);
Share:
973,706
Agnel Kurian
Author by

Agnel Kurian

Software Engineer with 18+ years of experience developing software in a wide range of areas: desktop, web, user interfaces, 2D/3D graphics, geometry, encryption and even structural analysis! I have a degree in Civil Engineering and a diploma from NIIT. I'm very comfortable on Linux. I like solving interesting problems.

Updated on July 20, 2022

Comments

  • Agnel Kurian
    Agnel Kurian almost 2 years

    I can create an array and initialize it like this:

    int a[] = {10, 20, 30};
    

    How do I create a std::vector and initialize it similarly elegant?

    The best way I know is:

    std::vector<int> ints;
    
    ints.push_back(10);
    ints.push_back(20);
    ints.push_back(30);
    

    Is there a better way?

  • Manuel
    Manuel about 14 years
    Of course I didn't downvote but I have a question anyway: when is the size of an array not a compile time constant? I.e., in which cases would you use the first solution in your second snippet as opposed to the third one?
  • Sebastian Mach
    Sebastian Mach about 14 years
    +vote from my side. In C++0x you could make a constexpr of option 1. But then again, this won't be used anymore then :S
  • David Rodríguez - dribeas
    David Rodríguez - dribeas about 14 years
    @Manuel, the size of the array is part of the type, and as such it is a compile time constant. Now, option 1 uses that compile time constant 'N' as return value for a function. The return of a function is not a compile time, but runtime value, even if it will probably get inlined as the constant value at the place of call. The difference is that you cannot do: int another[size_of_array(array)], while you can do int another[ARRAY_SIZE(array)].
  • sellibitze
    sellibitze about 14 years
    @Manuel: incomplete array types also exist, like int[]. I can put a declaration of such an array in a header and define it somewhere else (with completed type). Then, the size is not known during compilation of all other traslation units that just include the header. Array-to-pointer decay still works, sizeof does not.
  • Yacoby
    Yacoby about 14 years
    @Agnel It will work fine without static or const, however they both make it more explicit as to how it should be used and allow the compiler to make additional optimizations.
  • T.E.D.
    T.E.D. about 13 years
    I didn't downvoate this, but I was tempted. Mainly because this saves you almost nothing over just using the initialized array in the first place. However, that's really C++'s fault, not yours.
  • To1ne
    To1ne almost 13 years
    In option 3: I don't really get what you mean with "declared, undefined "? So the variable will not take additional memory?
  • David Rodríguez - dribeas
    David Rodríguez - dribeas over 12 years
    @To1ne that is actually a function declaration, not a variable. The reason for or defining it is that we don't actually want the function for anything else other than the sizeof expression that does not need a definition. While you can actually provide a definition, to do it right would require the static allocation of an array and returning a reference to it, and the next question would be what would make sense as values for the array? (Also note that this means one array per type/size combination of the function's instantiations!) Since the is no sensible use for it, I'd rather avoid it.
  • DomX23
    DomX23 over 12 years
    Can you explain why you're using those parameters when defining the vec vector.
  • Daniel Buckmaster
    Daniel Buckmaster about 12 years
    I haven't been able to figure out how to use this code, but it looks interesting.
  • Piti Ongmongkolkul
    Piti Ongmongkolkul about 12 years
    It's like one of the comment above said. Just overloading += and comma operator. Putting parenthesis for clarity : ((((v+=1),2),3),4),5) This is how it works: First, vector<T> += T returns a vector_inserter lets call it vi which encapsulate the original vector then vi,T add T to original vector which vi encapsulate and return it self so that we can do vi,T again.
  • Yevhen
    Yevhen almost 12 years
    this code didn't worked correctly on gcc 4.2.1 i think because of returning reference to a local variable inside += operator but idea is exellent. i edited code and there appears one more copy constructor. flow is now -> += -> ctor -> comma -> copy -> dtor -> comma ...... -> comma -> dtor.
  • Johnny Pauling
    Johnny Pauling over 11 years
    sizeof(array) is one of the few exceptions that allows to get the total size of elements of the array and NOT the arr pointer dimension. So basically he's using vector(pointer_to_first_element, pointer_to_first_element + size_in_bytes_of_the_whole_array / size_of_one_element) that is: vector(pointer_to_first_element, pointer_after_final_element). The type is already given with the <int>, so the vector knows how much is one element. Remember that iterators can be treated as pointers so you're basically using the vector(iterator begin, iterator end) constructor
  • Andres Riofrio
    Andres Riofrio over 11 years
    This technique can also be used to overload a function to accept an array with typed size.
  • Luis Machuca
    Luis Machuca over 11 years
    Not only is this method easy and standalone without any extra requirements, but it can also be made forwards-compatible with C++0x and their container initialization lists with the help of a macro, which eases syntax and portability a lot. +1.
  • Agnel Kurian
    Agnel Kurian over 11 years
    Which compiler? Are you using C++11 here?
  • Paul Baltescu
    Paul Baltescu over 11 years
    g++ 4.6.3 with -std=c++0x.
  • qwerty9967
    qwerty9967 about 11 years
    It seems that if I use static const string attr[]={"abc", "def","ghi"} that I can't use sizeof to get the array length. It also doesn't seem to work for arrays of char *'s. Am I doing something wrong?
  • qwerty9967
    qwerty9967 about 11 years
    Actually ... the sizeof trick works just fine until I pass the array into a function. Then it seems to not work any more. Is there a way around that?
  • Victor K
    Victor K about 11 years
    @qwerty9967 When you pass an array into a function by pointer, you should always pass the size of the array as well, unless the function infers the size of the array from the array contents (e.g. if the last element contains terminating value etc.). That's why C++ has std::vector, so passing it by reference will solve your problem.
  • pdk
    pdk over 10 years
    In the similar lines , I am trying to initialise the map, std::map<int, bool> catinfo = { {1, false} }; But then get this error error: in C++98 'catinfo' must be initialized by constructor, not by '{...}'
  • bobobobo
    bobobobo over 10 years
    I haven't seen a worse case of operator overloading abuse in a long time. Does the += there tack on 1,2,3,4.. to the end of values, or does it add 1 to the 1st element, 2 to the 2nd element, 3 to the 3rd element (as syntax like this should in MATLAB-like languages)
  • DarkWanderer
    DarkWanderer about 10 years
    @T.E.D: Sometimes you need to modify the resulting vector. For example, you may need to always have some default parameters and sometimes add a few customized to them.
  • Mike P
    Mike P over 9 years
    Question states C++ 03 (not 11)
  • shaveenk
    shaveenk over 9 years
    I think it didn't specify 03 when I answered this. Don't remember perfectly though. However, it is still a useful answer for someone looking for a quick solution.
  • Bernhard Barker
    Bernhard Barker about 9 years
    If you're using C++11 already, you may as well go for the direct approach - vector<int> arr = {10, 20, 30};.
  • Patryk
    Patryk about 9 years
    Can you explain the const T (&data)[N] part? How is the size of the array deduced in your call makeVector(values)?
  • Nebula
    Nebula almost 9 years
    Actually I had an incoming int[] (some C lib) and wanted to push into a vector (C++ lib). This answer helped, the rest didn't ;-)
  • Agnel Kurian
    Agnel Kurian about 8 years
    The armadillo library does this for matrix initialisation but uses the << operator instead of a named function: arma.sourceforge.net/docs.html#element_initialisation
  • MasterHD
    MasterHD almost 8 years
    Doesn't this imply that two duplicate copies of the integers are now being stored in memory? Is there at least a way to destroy the static const int arr[] afterward to free up that memory? Even without the static keyword, a global variable would remain allocated for the entirety of the program. This could become an issue when dealing with many/large vectors of doubles, strings, etc.
  • mhd
    mhd over 7 years
    The option 1 doesn't work in the case of empty array: int arr[0] = {}; std::size_t num = size_of_array(arr); Compiler will print something like: no matching function for call to 'size_of_array(int [0])' std::size_t num = size_of_array(arr);
  • David Rodríguez - dribeas
    David Rodríguez - dribeas over 7 years
    @mhd: You cannot construct an empty array in the language. 'int arr[0] = {};' is not valid C++ code. But you are right that if you want to initialize an empty vector and a non-empty vector you will have to use different constructs. Since C++11 this is a non-issue as you can use the initializer list constructor
  • Jaege
    Jaege over 7 years
    C++11 also support std::begin and std::end for array, so a vector can also be initialized like static const int arr[] = {10,20,30}; vector<int> vec(begin(arr), end(arr));.
  • einpoklum
    einpoklum about 7 years
    A solution involving an auxiliary variable, sizeof() and multiple arithmetic operations including a division is anything but "the easiest way". -1.
  • Speed8ump
    Speed8ump about 6 years
    I'd have probably overloaded << instead of +=. At least << already has vague side effect rules because of bit shifts and cout
  • Azurespot
    Azurespot about 6 years
    Since vectors are self-sizing, would it be ok to initialize it as empty too? Like in the constructor: this->vect = {}; ?
  • Luke
    Luke about 6 years
    @Azurespot You can just initialise it, and it will be empty: std::vector<T> vector;
  • Adam Erickson
    Adam Erickson over 5 years
    In fairness, this was originally a C++03 question, but I hope that people/companies adopt the new standards. C++ still needs a variable-length array (VLA) implementation in the standard library similar to what is available in Eigen and Boost.
  • Lightness Races in Orbit
    Lightness Races in Orbit about 5 years
    Unfortunately, this approach is problematic in some cases e.g. open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467. Yuck.
  • simomo
    simomo about 5 years
    Just in case somebody may be curious about std::vector<int> v = {1, 2, 3, 4};, vector's initializer list constructor will be called for this sort of initializing, its doc can be find in the C++ 11 section.
  • Don Hatch
    Don Hatch about 5 years
    Your ARRAY_SIZE macro #define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) is more unsafe than necessary. Please parenthesize it properly: #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) or #define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x)))
  • Adam Erickson
    Adam Erickson almost 5 years
    If "list-initialization of an aggregate from an object of the same type" is your thing, probably there are bigger problems in your codebase... I can think of no application where it would justify the debugging problems.
  • Noone AtAll
    Noone AtAll almost 4 years
    answer from 2018 and still uses ={}?
  • backslashN
    backslashN over 3 years
    Still no need of =
  • François Andrieux
    François Andrieux almost 3 years
    This answer could be slightly improved by accounting for the introduction of constexpr to the language.
  • templatetypedef
    templatetypedef almost 3 years
    Won't this deduce my_ints as a std::initializer_list<int> rather than a std::vector<int>?
  • templatetypedef
    templatetypedef almost 3 years
    That last one could be simplified to auto vect2 = vect1; or vector<int> vect2 = vect1, right?
  • templatetypedef
    templatetypedef almost 3 years
    Does this code compile? That last line looks like it would be a syntax error, since it would be parsed as (std::v).assign(arr, arr + len);, and there's no v in namespace std. Or did you mean std::vector<int> v; v.assign(...);?
  • ar2015
    ar2015 almost 3 years
    Doesn't work for a vector with a single element.
  • Adam Erickson
    Adam Erickson over 2 years
    The answer uses the = and {} symbols to simplify the translation for programmers coming from other languages. Omitting the assignment operator when you are in fact assigning values is just weird. The compiler will remove the = operator anyway.
  • Milan
    Milan about 2 years
    "For C++ 17 onwards we can omit the type" -- Thanks to Class template argument deduction (CTAD)
  • Alexis Wilke
    Alexis Wilke almost 2 years
    Note that for you can use: len = std::size(arr);. It does the same thing under the hood.