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?
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]) );
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.
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))
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.
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);
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.
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};
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};
La façon la plus simple de le faire est:
vector<int> ints = {10, 20, 30};
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.
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.
En C++ 11:
static const int a[] = {10, 20, 30};
vector<int> vec (begin(a), end(a));
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;
}
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;
}
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)
vous pouvez le faire en utilisant boost :: assign.
vector<int> values;
values += 1,2,3,4,5,6,7,8,9;
Les méthodes ci-dessous peuvent être utilisées pour initialiser le vecteur en c ++.
int arr[] = {1, 3, 5, 6}; vector<int> v(arr, arr + sizeof(arr)/sizeof(arr[0]));
vector<int>v; v.Push_back(1); v.Push_back(2); v.Push_back(3);
et ainsi de suite
vector<int>v = {1, 3, 5, 7};
Le troisième n’est autorisé que dans C++ 11.
// 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.
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);
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
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>
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!
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.
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
"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).