web-dev-qa-db-fra.com

Quel est le moyen le plus simple d'initialiser un std :: vector avec des éléments codés en dur?

Je peux créer un tableau et l'initialiser comme ceci:

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

Comment créer un std::vector et l'initialiser de manière élégante?

Le meilleur moyen que je connaisse est:

std::vector<int> ints;

ints.Push_back(10);
ints.Push_back(20);
ints.Push_back(30);

Y a-t-il un meilleur moyen?

567
Agnel Kurian

Une méthode consisterait à utiliser le tableau pour initialiser le vecteur

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

Si votre compilateur supporte C++ 11, vous pouvez simplement faire:

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

Ceci est disponible dans GCC à partir de la version 4.4 . Malheureusement, VC++ 2010 semble être à la traîne à cet égard.

Sinon, la bibliothèque Boost.Assign utilise une magie non macro pour permettre les opérations suivantes:

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

Ou:

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

Mais gardez à l'esprit que cela comporte des frais généraux (en général, list_of construit un std::deque sous le capot), donc pour un code essentiel à la performance, vous feriez mieux de faire ce que Yacoby dit.

594
Manuel

En C++ 0x, vous pourrez le faire de la même manière qu'avec un tableau, mais pas dans le standard actuel.

Avec uniquement un support linguistique, vous pouvez utiliser:

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

Si vous pouvez ajouter d'autres bibliothèques, vous pouvez essayer boost :: Affectation:

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

Pour éviter de coder en dur la taille d'un tableau:

// 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))
76

Si vous le pouvez, utilisez la méthode moderne C++ [11,14,17, ...]:

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

L'ancienne façon de boucler sur un tableau de longueur variable ou d'utiliser sizeof() est vraiment terrible pour les yeux et totalement inutile en termes de surcharge mentale. Beurk.

75
Adam Erickson

En C++ 11:

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

Utiliser boost list_of:

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

Utilisation de boost assign:

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

STL conventionnel:

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

STL conventionnel avec macros génériques:

#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));

STL conventionnelle avec une macro d'initialisation vectorielle:

#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);
56
mbells

Je pensais juste que je mettrais mes 0,02 $. J'ai tendance à déclarer ceci:

template< typename T, size_t N >
std::vector<T> makeVector( const T (&data)[N] )
{
    return std::vector<T>(data, data+N);
}

dans un en-tête d'utilitaire quelque part et tout ce qui est nécessaire est:

const double values[] = { 2.0, 1.0, 42.0, -7 };
std::vector<double> array = makeVector(values);

Mais je ne peux pas attendre pour C++ 0x. Je suis bloqué parce que mon code doit également être compilé dans Visual Studio. Huer.

52
M. Tibbits

Avant C++ 11:

Méthode 1 =>

vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
vector<int>v;

Méthode 2 =>

 v.Push_back(SomeValue);

C++ 11 ci-dessous est également possible

vector<int>v = {1, 3, 5, 7};
34
A J

Commençant par:

int a[] = {10, 20, 30}; //i'm assuming a is just a placeholder

Si vous n'avez pas de compilateur C++ 11 et que vous ne voulez pas utiliser boost:

const int a[] = {10, 20, 30};
const std::vector<int> ints(a,a+sizeof(a)/sizeof(int)); //make it const if you can

Si vous ne possédez pas de compilateur C++ 11 et pouvez utiliser boost:

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

Si vous avez un compilateur C++ 11:

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

La façon la plus simple de le faire est:

vector<int> ints = {10, 20, 30};
21
Paul Baltescu

Pour l'initialisation vectorielle -

vector<int> v = {10,20,30}

peut être fait si vous avez le compilateur c ++ 11.

Sinon, vous pouvez avoir un tableau des données, puis utiliser une boucle for.

int array[] = {10,20,30}
for(unsigned int i=0; i<sizeof(array)/sizeof(array[0]); i++)
{
     v.Push_back(array[i]);
}

En dehors de ceux-ci, il existe divers autres moyens décrits ci-dessus en utilisant du code. À mon avis, ces moyens sont faciles à retenir et rapides à écrire.

20
Tush_08

Si votre compilateur prend en charge macros variadic (ce qui est vrai pour les compilateurs les plus modernes), vous pouvez utiliser la macro suivante pour transformer l'initialisation du vecteur en une ligne:

#define INIT_VECTOR(type, name, ...) \
static const type name##_a[] = __VA_ARGS__; \
vector<type> name(name##_a, name##_a + sizeof(name##_a) / sizeof(*name##_a))

Avec cette macro, vous pouvez définir un vecteur initialisé avec le code suivant:

INIT_VECTOR(int, my_vector, {1, 2, 3, 4});

Cela créerait un nouveau vecteur d'ints nommé my_vector avec les éléments 1, 2, 3, 4.

14
Matt Ball

En C++ 11:

static const int a[] = {10, 20, 30};
vector<int> vec (begin(a), end(a));
11
BufBills

Si vous ne voulez pas utiliser boost, mais voulez profiter de la syntaxe comme

std::vector<int> v;
v+=1,2,3,4,5;

il suffit d'inclure ce morceau de code

template <class T> class vector_inserter{
public:
    std::vector<T>& v;
    vector_inserter(std::vector<T>& v):v(v){}
    vector_inserter& operator,(const T& val){v.Push_back(val);return *this;}
};
template <class T> vector_inserter<T> operator+=(std::vector<T>& v,const T& x){
    return vector_inserter<T>(v),x;
}
11
Piti Ongmongkolkul

Je construis ma propre solution en utilisant va_arg. Cette solution est conforme à C++ 98.

#include <cstdarg>
#include <iostream>
#include <vector>

template <typename T>
std::vector<T> initVector (int len, ...)
{
  std::vector<T> v;
  va_list vl;
  va_start(vl, len);
  for (int i = 0; i < len; ++i)
    v.Push_back(va_arg(vl, T));
  va_end(vl);
  return v;
}

int main ()
{
  std::vector<int> v = initVector<int> (7,702,422,631,834,892,104,772);
  for (std::vector<int>::const_iterator it = v.begin() ; it != v.end(); ++it)
    std::cout << *it << std::endl;
  return 0;
}

démo

11
aloisdg

Une question dupliquée plus récente a cette réponse par Viktor Sehr . Pour moi, il est compact, visuellement attrayant (on dirait que vous "transférez" les valeurs), ne nécessite pas de module c ++ 11 ou tiers, et évite l'utilisation d'une variable supplémentaire (écrite). Voici comment je l’utilise avec quelques modifications. Je pourrais passer à l’extension future de la fonction de vecteur et/ou de va_arg.


// Based on answer by "Viktor Sehr" on Stack Overflow
// https://stackoverflow.com/a/8907356
//
template <typename T>
class mkvec {
public:
    typedef mkvec<T> my_type;
    my_type& operator<< (const T& val) {
        data_.Push_back(val);
        return *this;
    }
    my_type& operator<< (const std::vector<T>& inVector) {
        this->data_.reserve(this->data_.size() + inVector.size());
        this->data_.insert(this->data_.end(), inVector.begin(), inVector.end());
        return *this;
    }
    operator std::vector<T>() const {
        return data_;
    }
private:
    std::vector<T> data_;
};

std::vector<int32_t>    vec1;
std::vector<int32_t>    vec2;

vec1 = mkvec<int32_t>() << 5 << 8 << 19 << 79;  
// vec1 = (5,8,19,79)
vec2 = mkvec<int32_t>() << 1 << 2 << 3 << vec1 << 10 << 11 << 12;  
// vec2 = (1,2,3,5,8,19,79,10,11,12)
10
Othermusketeer

vous pouvez le faire en utilisant boost :: assign.

vector<int> values;  
values += 1,2,3,4,5,6,7,8,9;

détail ici

10
f4.

Les méthodes ci-dessous peuvent être utilisées pour initialiser le vecteur en c ++.

  1. int arr[] = {1, 3, 5, 6}; vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));

  2. vector<int>v; v.Push_back(1); v.Push_back(2); v.Push_back(3); et ainsi de suite

  3. vector<int>v = {1, 3, 5, 7};

Le troisième n’est autorisé que dans C++ 11.

6
Jay
// Before C++11
// I used following methods:

// 1.
int A[] = {10, 20, 30};                              // original array A

unsigned sizeOfA = sizeof(A)/sizeof(A[0]);           // calculate the number of elements

                                                     // declare vector vArrayA,
std::vector<int> vArrayA(sizeOfA);                   // make room for all
                                                     // array A integers
                                                     // and initialize them to 0 

for(unsigned i=0; i<sizeOfA; i++)
    vArrayA[i] = A[i];                               // initialize vector vArrayA


//2.
int B[] = {40, 50, 60, 70};                          // original array B

std::vector<int> vArrayB;                            // declare vector vArrayB
for (unsigned i=0; i<sizeof(B)/sizeof(B[0]); i++)
    vArrayB.Push_back(B[i]);                         // initialize vArrayB

//3.
int C[] = {1, 2, 3, 4};                              // original array C

std::vector<int> vArrayC;                            // create an empty vector vArrayC
vArrayC.resize(sizeof(C)/sizeof(C[0]));              // enlarging the number of 
                                                     // contained elements
for (unsigned i=0; i<sizeof(C)/sizeof(C[0]); i++)
     vArrayC.at(i) = C[i];                           // initialize vArrayC


// A Note:
// Above methods will work well for complex arrays
// with structures as its elements.
5
sg7

Si vous voulez quelque chose dans le même ordre général que Boost :: assign sans créer de dépendance à Boost, ce qui suit est au moins vaguement similaire:

template<class T>
class make_vector {
    std::vector<T> data;
public:
    make_vector(T const &val) { 
        data.Push_back(val);
    }

    make_vector<T> &operator,(T const &t) {
        data.Push_back(t);
        return *this;
    }

    operator std::vector<T>() { return data; }
};

template<class T> 
make_vector<T> makeVect(T const &t) { 
    return make_vector<T>(t);
}

Bien que je souhaite que la syntaxe d'utilisation soit plus propre, ce n'est toujours pas affreux:

std::vector<int> x = (makeVect(1), 2, 3, 4);
4
Jerry Coffin

Si le tableau est:

int arr[] = {1, 2, 3};
int len = (sizeof(arr)/sizeof(arr[0])); // finding length of array
vector < int > v;
std:: v.assign(arr, arr+len); // assigning elements from array to vector 
4
FaridLU
typedef std::vector<int> arr;

arr a {10, 20, 30};       // This would be how you initialize while defining

Pour compiler utiliser:

clang++ -std=c++11 -stdlib=libc++  <filename.cpp>
4
shaveenk

Il y a beaucoup de bonnes réponses ici, mais depuis que je suis arrivé de façon indépendante avant de lire ceci, je me suis dit que je jeterais les miennes ici de toute façon ...

Voici une méthode que j'utilise pour cela et qui fonctionnera universellement sur les compilateurs et les plates-formes:

Créez une structure ou une classe en tant que conteneur pour votre collection d'objets. Définir une fonction de surcharge d'opérateur pour <<.

class MyObject;

struct MyObjectList
{
    std::list<MyObject> objects;
    MyObjectList& operator<<( const MyObject o )
    { 
        objects.Push_back( o );
        return *this; 
    }
};

Vous pouvez créer des fonctions qui prennent votre structure en paramètre, par exemple:

someFunc( MyObjectList &objects );

Ensuite, vous pouvez appeler cette fonction, comme ceci:

someFunc( MyObjectList() << MyObject(1) <<  MyObject(2) <<  MyObject(3) );

De cette façon, vous pouvez créer et transmettre une collection d'objets de taille dynamique à une fonction dans une seule ligne épurée!

4
BuvinJ

En relation, vous pouvez utiliser ce qui suit si vous souhaitez qu'un vecteur soit complètement prêt à être inséré dans une instruction rapide (par exemple, passer immédiatement à une autre fonction):

#define VECTOR(first,...) \
   ([](){ \
   static const decltype(first) arr[] = { first,__VA_ARGS__ }; \
   std::vector<decltype(first)> ret(arr, arr + sizeof(arr) / sizeof(*arr)); \
   return ret;})()

exemple de fonction

template<typename T>
void test(std::vector<T>& values)
{
    for(T value : values)
        std::cout<<value<<std::endl;
}

exemple d'utilisation

test(VECTOR(1.2f,2,3,4,5,6));

attention toutefois au decltype, assurez-vous que la première valeur est clairement ce que vous voulez.

3
Josh

B. Stroustrup décrit une manière agréable d’enchaîner des opérations en 16.2.10 Selfreference à la page 464 dans l’édition C++ 11 du prog. Lang. où une fonction retourne une référence, ici modifiée en un vecteur. De cette façon, vous pouvez enchaîner comme v.pb(1).pb(2).pb(3); mais cela peut être trop de travail pour de si petits gains.

#include <iostream>
#include <vector>

template<typename T>
class chain
{
private:
    std::vector<T> _v;
public:
    chain& pb(T a) {
        _v.Push_back(a);
        return *this;
    };
    std::vector<T> get() { return _v; };
};

using namespace std;

int main(int argc, char const *argv[])
{
    chain<int> v{};

    v.pb(1).pb(2).pb(3);

    for (auto& i : v.get()) {
        cout << i << endl;
    }

    return 0;
}

1
2
3

2
kometen

"Comment créer un vecteur STL et l'initialiser comme ci-dessus? Quelle est la meilleure façon de le faire avec le moins de frappe possible?"

Le moyen le plus simple d'initialiser un vecteur lorsque vous avez initialisé votre tableau intégré consiste à utiliser une liste d'initialiseurs introduite en C++ 11 .

// Initializing a vector that holds 2 elements of type int.
Initializing:
std::vector<int> ivec = {10, 20};


// The Push_back function is more of a form of assignment with the exception of course
//that it doesn't obliterate the value of the object it's being called on.
Assigning
ivec.Push_back(30);

ivec a une taille de 3 éléments après l’exécution de Assigning (instruction étiquetée).

2
user2103487