706 votes

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 aussi é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 ?

1 votes

Si vous n'avez pas l'intention de modifier la taille des ints après l'initialisation, envisagez d'utiliser le tableau tr1.

1 votes

@zr, je suis curieux... si j'avais besoin d'une taille fixe, ne pourrais-je pas utiliser les vieux tableaux eux-mêmes ? Je regarde le tableau tr1 en ce moment...

2 votes

tr1::array est utile parce que les tableaux ordinaires ne fournissent pas l'interface des conteneurs STL.

758voto

Manuel Points 5396

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.

Alternativement, le Boost.Assign utilise la magie non-macro pour permettre ce qui suit :

#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 entraîne des frais généraux (essentiellement, list_of construit un std::deque sous le capot), donc pour du code critique en termes de performances, il vaut mieux faire comme Yacoby.

0 votes

Puisque les vecteurs sont autodimensionnés, serait-il possible de les initialiser comme étant vides également ? Comme dans le constructeur : this->vect = {}; ?

3 votes

@Azurespot Vous pouvez simplement l'initialiser, et il sera vide : std::vector<T> vector;

2 votes

Juste au cas où quelqu'un serait curieux de savoir std::vector<int> v = {1, 2, 3, 4}; , le vecteur est initializer list constructor sera appelé pour ce genre d'initialisation, sa doc peut être trouvée dans le fichier C++ 11 section .

583voto

Yacoby Points 29771

Une méthode serait d'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]) );

7 votes

@Agnel Il fonctionnera très bien sans static o const Cependant, ils sont tous deux plus explicites quant à la façon dont ils doivent être utilisés et permettent au compilateur d'effectuer des optimisations supplémentaires.

78 votes

Je ne l'ai pas descendu, mais j'ai été tenté. Principalement parce que cela n'économise presque rien par rapport à l'utilisation du tableau initialisé en premier lieu. Cependant, c'est vraiment la faute du C++, pas la vôtre.

2 votes

Pouvez-vous expliquer pourquoi vous utilisez ces paramètres pour définir le vecteur vec.

81voto

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

Avec le seul support linguistique que 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::assignment :

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

0 votes

Bien sûr, je n'ai pas descendu le vote, mais j'ai quand même une question : quand la taille d'un tableau n'est-elle pas une constante de temps de compilation ? En d'autres termes, dans quels cas utiliseriez-vous la première solution de votre deuxième extrait plutôt que la troisième ?

0 votes

+vote de mon côté. En C++0x, on pouvait faire un constexpr de l'option 1. Mais là encore, il ne sera plus utilisé :S

4 votes

Manuel, la taille du tableau fait partie du type, et en tant que telle, c'est une constante de compilation. Maintenant, l'option 1 utilise cette constante de compilation 'N' comme valeur de retour pour une fonction. Le retour d'une fonction n'est pas une valeur de compilation, mais une valeur d'exécution, même si elle sera probablement intégrée comme valeur constante à l'endroit de l'appel. La différence est que vous ne pouvez pas le faire : int another[size_of_array(array)] alors que vous pouvez faire int another[ARRAY_SIZE(array)] .

80voto

mbells Points 398

En C++11 :

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

Utilisation de 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 l'assignation Boost :

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

Conventionnel STL :

#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 conventionnel avec une macro d'initialisation de vecteur :

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

5 votes

C++11 supporte également std::begin y std::end pour un tableau, donc un vecteur peut aussi être initialisé de la manière suivante static const int arr[] = {10,20,30}; vector<int> vec(begin(arr), end(arr)); .

58voto

M. Tibbits Points 3867

J'ai tendance à déclarer

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 ensuite tout ce qui est nécessaire est :

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

1 votes

Cette technique peut également être utilisée pour surcharger une fonction afin d'accepter un tableau avec une taille typée.

4 votes

Pouvez-vous expliquer le const T (&data)[N] partie ? Comment la taille du tableau est-elle déduite dans votre appel ? makeVector(values) ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X