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




initialize ejemplo (21)

En C ++ 11:

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

Puedo crear una matriz e inicializarla de esta manera:

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

¿Cómo creo un std::vector y lo inicializo de manera similar?

La mejor manera que conozco es:

std::vector<int> ints;

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

¿Hay alguna manera mejor?


En C ++ 11:

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

Usando boost list_of:

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

Usando boost assign:

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

STL convencional:

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

STL convencional con macros genéricos:

#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 convencional con una macro de inicializador vectorial:

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

Si no quieres usar boost, pero quieres disfrutar de la sintaxis como

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

solo incluye este trozo de código

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;
}

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

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

función de ejemplo

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

ejemplo de uso

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

aunque tenga cuidado con el tipo de letra, asegúrese de que el primer valor sea claramente lo que desea.


Para inicialización de vectores -

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

Se puede hacer si tienes el compilador de c ++ 11.

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

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

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


puedes hacerlo usando boost :: assign.

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

detalle aqui


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

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

en un encabezado de utilidad en algún lugar y luego todo lo que se requiere es:

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

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


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 

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

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

Demo


Si su compilador admite macros Variadic (lo cual es cierto para la mayoría de los compiladores modernos), entonces puede usar la siguiente macro para convertir la inicialización de vectores en una sola línea:

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

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 entradas llamado my_vector con los elementos 1, 2, 3, 4.


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

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

typedef std::vector<int> arr;

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

Para compilar el uso:

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

B. Stroustrup describe una buena manera de encadenar operaciones en 16.2.10 Selfreference 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 manera puedes encadenar como v.pb(1).pb(2).pb(3); pero puede ser demasiado trabajo para tan pequeñas ganancias.

#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


Por el amor de Dios, use el moderno C ++ [11,14,17, ...] manera:

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

La antigua forma de recorrer un conjunto de longitud variable o usar sizeof() es realmente terrible para los ojos y completamente innecesaria en términos de sobrecarga mental. Puaj


Si su compilador soporta C ++ 11, simplemente puede hacer:

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

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

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

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

O:

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

Pero tenga en cuenta que esto tiene cierta sobrecarga (básicamente, list_of construye un std::deque debajo del capó), por lo que para el código crítico para el rendimiento sería mejor hacerlo como dice Yacoby.


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

// Based on answer by "Viktor Sehr" on 
// https://.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)

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

Aunque deseo que la sintaxis para usarla sea más limpia, todavía no es particularmente horrible:

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

Los siguientes métodos pueden utilizarse para inicializar el vector 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); y así

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

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


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 idioma puedes usar:

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

Si puedes agregar otras bibliotecas, puedes probar boost :: tarea:

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

Para evitar codificar el tamaño de una matriz:

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

// 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.

También puedes hacer esto:

template <typename T>
class make_vector {
public:
  typedef make_vector<T> my_type;
  my_type& operator<< (const T& val) {
    data_.push_back(val);
    return *this;
  }
  operator std::vector<T>() const {
    return data_;
  }
private:
  std::vector<T> data_;
};

Y úsalo así:

std::vector<int> v = make_vector<int>() << 1 << 2 << 3;




c++ vector initialization