c++ - zeros - vector constructor




Qual è il modo più semplice per inizializzare un vettore std:: con elementi hardcoded? (17)

B. Stroustrup descrive un buon modo per concatenare le operazioni in 16.2.10 Selfreference a pagina 464 nell'edizione C ++ 11 del Prog. Lang. dove una funzione restituisce un riferimento, qui modificato in un vettore. In questo modo puoi concatenare come v.pb(1).pb(2).pb(3); ma potrebbe essere troppo lavoro per guadagni così piccoli.

#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

Posso creare un array e inizializzarlo in questo modo:

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

Come posso creare un std::vector e inizializzarlo in modo altrettanto elegante?

Il modo migliore che conosco è:

std::vector<int> ints;

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

Esiste un modo migliore?


Ci sono molte buone risposte qui, ma siccome sono arrivato da solo in autonomia prima di leggere questo, ho pensato di buttare il mio qui comunque ...

Ecco un metodo che sto usando per questo che funzionerà universalmente su compilatori e piattaforme:

Crea una struct o una classe come contenitore per la tua collezione di oggetti. Definire una funzione di sovraccarico dell'operatore per <<.

class MyObject;

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

Puoi creare funzioni che prendono la tua struct come parametro, ad esempio:

someFunc( MyObjectList &objects );

Quindi, puoi chiamare quella funzione, in questo modo:

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

In questo modo, puoi creare e passare una raccolta di oggetti di dimensioni dinamiche a una funzione in un'unica riga pulita!


Costruisco la mia soluzione utilizzando va_arg . Questa soluzione è conforme a 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


Di seguito i metodi possono essere utilizzati per inizializzare il vettore in 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); e così via

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

Il terzo è consentito solo in C ++ 11 in poi.


Il modo più semplice per farlo è:

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

In C ++ 0x sarete in grado di farlo nello stesso modo in cui avete fatto con un array, ma non nello standard corrente.

Con il solo supporto linguistico puoi usare:

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

Se puoi aggiungere altre librerie puoi provare boost :: assignment:

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

Per evitare la codifica hard della dimensione di un array:

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

In C ++ 11:

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

Iniziare con:

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

Se non hai un compilatore C ++ 11 e non vuoi usare boost:

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

Se non hai un compilatore C ++ 11 e puoi usare boost:

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

Se hai un compilatore C ++ 11:

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

Per l'inizializzazione del vettore -

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

può essere fatto se hai il compilatore c ++ 11.

Altrimenti, è possibile avere una matrice di dati e quindi utilizzare un ciclo for.

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

Oltre a questi, ci sono vari altri modi descritti sopra usando del codice. Secondo me, questi modi sono facili da ricordare e veloci da scrivere.


Prima del C ++ 11:

Metodo 1 =>

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

Metodo 2 =>

 v.push_back(SomeValue);

È possibile anche C ++ 11 in seguito

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

Se il tuo compilatore supporta C ++ 11, puoi semplicemente fare:

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

Questo è disponibile in GCC dalla versione 4.4 . Sfortunatamente, VC ++ 2010 sembra essere in ritardo in questo senso.

In alternativa, la libreria Boost.Assign utilizza la magia non macro per consentire quanto segue:

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

Ma tieni a mente che questo ha un sovraccarico (in pratica, list_of costruisce un std::deque sotto il cofano) quindi per il codice critico delle prestazioni faresti meglio a fare come dice Yacoby.


Se la matrice è:

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 

Se vuoi qualcosa sullo stesso ordine generale di Boost :: assign senza creare una dipendenza da Boost, quanto segue è almeno vagamente simile:

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

Mentre spero che la sintassi per usarlo sia più pulito, non è ancora particolarmente terribile:

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

Un metodo sarebbe utilizzare la matrice per inizializzare il vettore

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

puoi farlo usando boost :: assign.

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

dettaglio qui


"Come posso creare un vettore STL e inizializzarlo come sopra? Qual è il modo migliore per farlo con il minimo sforzo di battitura?"

Il modo più semplice per inizializzare un vettore quando hai inizializzato il tuo array incorporato sta usando un elenco di inizializzatore che è stato introdotto in 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 ha una dimensione di 3 elementi dopo l'esecuzione dell'istruzione (istruzione etichettata).


typedef std::vector<int> arr;

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

Per compilare l'uso:

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






initialization