¿Cuál es la forma más fácil de inicializar un std :: vector con elementos codificados?

Puedo crear una matriz e inicializarla así:

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

¿Cómo creo un std::vector e inicializo de manera similar elegante?

La mejor manera que conozco es:

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

¿Hay una mejor manera?

Un método sería usar la matriz para inicializar el vector

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

Si su comstackdor es compatible con C ++ 11, simplemente puede hacer:

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

Esto está disponible en GCC a partir de la versión 4.4 . Lamentablemente, VC ++ 2010 parece estar rezagado en este sentido.

Alternativamente, la biblioteca Boost.Assign utiliza magia no macro para permitir lo siguiente:

 #include  ... std::vector v = boost::assign::list_of(1)(2)(3)(4); 

O:

 #include  using namespace boost::assign; ... std::vector v; v += 1, 2, 3, 4; 

Pero tenga en cuenta que esto tiene algunos gastos generales (básicamente, list_of a std::deque debajo del capó), por lo que para el código de rendimiento crítico sería mejor que haga lo que dice Yacoby.

En C ++ 0x podrá hacerlo de la misma manera que lo hizo con una matriz, pero no en el estándar actual.

Con solo soporte de idiomas, puede usar:

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

Si puede agregar otras bibliotecas, puede probar boost :: assignment:

 vector v = list_of(10)(20)(30); 

Para evitar codificar de forma rígida el tamaño de una matriz:

 // option 1, typesafe, not a compile time constant template  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  char (&sizeof_array( T(&)[N] ))[N]; // declared, undefined #define ARRAY_SIZE(x) sizeof(sizeof_array(x)) 

Solo pensé en tirar mi $ 0.02. Tiendo a declarar esto:

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

en un encabezado de utilidad en alguna parte y luego todo lo que se requiere es:

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

Pero no puedo esperar para C ++ 0x. Estoy atascado porque mi código también debe comstackrse en Visual Studio. Abucheo.

En C ++ 11:

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

Usando boost list_of:

 #include  #include  using std::vector; ... vector vec = boost::assign::list_of(10)(20)(30); 

Usando la asignación de impulso:

 #include  #include  using std::vector; ... vector vec; vec += 10, 20, 30; 

STL convencional:

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

STL convencional con macros genéricas:

 #include  #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 vec (arr, ARRAY_END(arr)); 

STL convencional con una macro inicializador de vector:

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

Antes de C ++ 11:

Método 1 =>

 vector v(arr, arr + sizeof(arr)/sizeof(arr[0])); vectorv; 

Método 2 =>

  v.push_back(SomeValue); 

C ++ 11 en adelante a continuación también es posible

 vectorv = {1, 3, 5, 7}; 

Empezando con:

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

Si no tiene un comstackdor de C ++ 11 y no quiere usar boost:

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

Si no tiene un comstackdor C ++ 11 y puede usar boost:

 #include  const std::vector ints = boost::assign::list_of(10)(20)(30); 

Si tienes un comstackdor C ++ 11:

 const std::vector ints = {10,20,30}; 

Por el amor de Dios, usa la forma moderna de C ++ [11,14,17, …]:

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

La antigua forma de recorrer una matriz de longitud variable o usar sizeof() es realmente terrible en los ojos y completamente innecesaria en términos de sobrecarga mental. Yuck.

La forma más fácil de hacerlo es:

 vector ints = {10, 20, 30}; 

Para la inicialización del vector –

 vector v = {10,20,30} 

se puede hacer si tiene el comstackdor c ++ 11.

De lo contrario, puede tener una matriz de datos y luego usar un ciclo for.

 int array[] = {10,20,30} for(int i=0; i 

Además de estos, hay varias otras maneras descritas arriba usando algún código. En mi opinión, estas formas son fáciles de recordar y rápidas de escribir.

Si su comstackdor admite macros Variadic (que es cierto para la mayoría de los comstackdores modernos), entonces puede usar la siguiente macro para convertir la inicialización vectorial en una línea única:

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

Con esta macro, puede definir un vector inicializado con un código como este:

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

Esto crearía un nuevo vector de ints llamado my_vector con los elementos 1, 2, 3, 4.

Si no quieres usar boost, pero quieres disfrutar de syntax como

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

solo incluye este trozo de código

 template  class vector_inserter{ public: std::vector& v; vector_inserter(std::vector& v):v(v){} vector_inserter& operator,(const T& val){v.push_back(val);return *this;} }; template  vector_inserter operator+=(std::vector& v,const T& x){ return vector_inserter(v),x; } 

puedes hacer eso usando boost :: assign.

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

detalle aquí

En C ++ 11:

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

Construyo mi propia solución usando va_arg . Esta solución cumple con C98.

 #include  #include  #include  template  std::vector initVector (int len, ...) { std::vector 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 v = initVector (7,702,422,631,834,892,104,772); for (std::vector::const_iterator it = v.begin() ; it != v.end(); ++it) std::cout << *it << std::endl; return 0; } 

Manifestación

Una pregunta duplicada más reciente tiene esta respuesta de Viktor Sehr . Para mí, es compacto, visualmente atractivo (parece que está “empujando” los valores), no requiere c ++ 11 o un módulo de terceros, y evita usar una variable adicional (escrita). A continuación se muestra cómo lo estoy usando con algunos cambios. Puedo pasar a extender la función de vector y / o va_arg en el futuro.


 // Based on answer by "Viktor Sehr" on Stack Overflow // https://stackoverflow.com/a/8907356 // template  class mkvec { public: typedef mkvec my_type; my_type& operator<< (const T& val) { data_.push_back(val); return *this; } my_type& operator<< (const std::vector& inVector) { this->data_.reserve(this->data_.size() + inVector.size()); this->data_.insert(this->data_.end(), inVector.begin(), inVector.end()); return *this; } operator std::vector() const { return data_; } private: std::vector data_; }; std::vector vec1; std::vector vec2; vec1 = mkvec() << 5 << 8 << 19 << 79; // vec1 = (5,8,19,79) vec2 = mkvec() << 1 << 2 << 3 << vec1 << 10 << 11 << 12; // vec2 = (1,2,3,5,8,19,79,10,11,12) 

Debajo se pueden usar métodos para inicializar el vector en c ++.

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

  2. vectorv; v.push_back(1); v.push_back(2); v.push_back(3); y así

  3. vectorv = {1, 3, 5, 7};

El tercero solo está permitido en C ++ 11 en adelante.

Si desea algo en el mismo orden general que Boost :: assign sin crear una dependencia en Boost, lo siguiente es al menos vagamente similar:

 template class make_vector { std::vector data; public: make_vector(T const &val) { data.push_back(val); } make_vector &operator,(T const &t) { data.push_back(t); return *this; } operator std::vector() { return data; } }; template make_vector makeVect(T const &t) { return make_vector(t); } 

Si bien deseo que la syntax para usarlo sea más limpia, todavía no es particularmente horrible:

 std::vector x = (makeVect(1), 2, 3, 4); 
 typedef std::vector arr; arr a {10, 20, 30}; // This would be how you initialize while defining 

Para comstackr el uso:

 clang++ -std=c++11 -stdlib=libc++  

Aquí hay muchas buenas respuestas, pero como llegué por mi cuenta de forma independiente antes de leer esto, de todos modos pensé en tirar el mío aquí …

Aquí hay un método que estoy usando para esto que funcionará universalmente en comstackdores y plataformas:

Crea una estructura o clase como un contenedor para tu colección de objetos. Definir una función de sobrecarga del operador para <<.

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

Puede crear funciones que toman su estructura como un parámetro, por ejemplo:

 someFunc( MyObjectList &objects ); 

Entonces, puedes llamar a esa función, así:

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

¡De esta forma, puedes construir y pasar una colección de objetos de tamaño dynamic a una función en una sola línea limpia!

 // 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 vArrayA(sizeOfA); // make room for all // array A integers // and initialize them to 0 for(unsigned i=0; i vArrayB; // declare vector vArrayB for (unsigned i=0; i vArrayC; // create an empty vector vArrayC vArrayC.resize(sizeof(C)/sizeof(C[0])); // enlarging the number of // contained elements for (unsigned i=0; i 

Si la matriz es:

 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 

“¿Cómo creo un vector STL e inicializo como lo anterior? ¿Cuál es la mejor manera de hacerlo con el mínimo esfuerzo de tipeo?”

La forma más fácil de inicializar un vector cuando ha inicializado su matriz incorporada es utilizando una lista de inicializadores que se introdujo en C ++ 11 .

 // Initializing a vector that holds 2 elements of type int. Initializing: std::vector 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 tiene 3 elementos de tamaño después de que se ejecuta la asignación (instrucción etiquetada).

Relacionado, puede usar lo siguiente si desea tener un vector completamente listo para entrar en una statement rápida (por ejemplo, pasar inmediatamente a otra función):

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

función de ejemplo

 template void test(std::vector& values) { for(T value : values) std::cout< 

ejemplo de uso

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

aunque ten cuidado con el tipo de declet, asegúrate de que el primer valor sea claramente lo que deseas.

B. Stroustrup describe una buena forma de encadenar operaciones en 16.2.10 Autorreferencia en la página 464 en la edición C ++ 11 del Prog. Lang. donde una función devuelve una referencia, aquí modificada a un vector. De esta forma puede encadenar como v.pb(1).pb(2).pb(3); pero puede ser demasiado trabajo para ganancias tan pequeñas.

 #include  #include  template class chain { private: std::vector _v; public: chain& pb(T a) { _v.push_back(a); return *this; }; std::vector get() { return _v; }; }; using namespace std; int main(int argc, char const *argv[]) { chain v{}; v.pb(1).pb(2).pb(3); for (auto& i : v.get()) { cout << i << endl; } return 0; } 

1
2
3