Wat is de gemakkelijkste manier om een ​​STD :: Vector met hardcodeerde elementen te initialiseren?

Ik kan een array maken en deze initialiseren:

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

Hoe maak ik een std::vectoren initialiseer het op dezelfde manier elegant?

De beste manier die ik ken is:

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

Is er een betere manier?


Antwoord 1, Autoriteit 100%

Eén methode zou zijn om de array te gebruiken om de vector

te initialiseren

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

Antwoord 2, Autoriteit 122%

Als uw compiler C++ 11 ondersteunt, kunt u eenvoudig doen:

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

Dit is beschikbaar in GCC vanaf versie 4.4 . Helaas lijkt VC++ 2010 in dit opzicht achterblijven.

Als alternatief, de Boost.Assign Bibliotheek maakt gebruik van niet-macro-magie om het volgende toe te staan:

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

of:

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

Maar houd er rekening mee dat dit enige overhead heeft (in feite maakt list_ofeen std::dequeonder de motorkap), dus voor prestatiekritieke code zou je het is beter om te doen wat Yacoby zegt.


Antwoord 3, autoriteit 21%

Als je kunt, gebruik dan de moderne C++[11,14,17,20,…] manier:

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

De oude manier om een array van variabele lengte te doorlopen of sizeof()te gebruiken, is echt verschrikkelijk voor de ogen en volledig onnodig in termen van mentale overhead. Bah.


Antwoord 4, autoriteit 14%

In C++0x kun je het op dezelfde manier doen als met een array, maar niet in de huidige standaard.

Met alleen taalondersteuning die u kunt gebruiken:

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

Als je andere bibliotheken kunt toevoegen, kun je boost::assignment:

. proberen

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

Om de grootte van een array hard te coderen:

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

Antwoord 5, Autoriteit 12%

In C++ 11:

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

BOOST gebruiken list_of:

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

Gebruik boost toewijzen:

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

Conventionele STL:

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

Conventionele stl met generieke macro’s:

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

Conventionele STL met een vector initializer Macro:

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

Antwoord 6, Autoriteit 10%

Ik heb de neiging om

te verklaren

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

in een hulpprogramma-header ergens en dan is alles wat nodig is:

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

Antwoord 7, autoriteit 7%

Vóór C++ 11:

Methode 1

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

Methode 2

v.push_back(SomeValue);

C++ 11 en later hieronder is ook mogelijk

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

Wij kunnen dit ook

vector<int>v {1, 3, 5, 7}; // Notice .. no "=" sign

Voor C++ 17 en later kunnen we het type weglaten

vector v = {1, 3, 5, 7};

Antwoord 8, autoriteit 5%

Vanaf:

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

Als je geen C++11-compiler hebt en je wilt Boost niet gebruiken:

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

Als u geen C++ 11-compiler hebt en BOOST kunt gebruiken:

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

Als u een C++ 11-compiler heeft:

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

Antwoord 9, Autoriteit 4%

voor vectorinitialisatie –

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

kan worden gedaan als u een C++ 11 compiler.

anders kunt u een array van de gegevens hebben en vervolgens een gebruiken voor -lus.

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

Afgezien hiervan zijn er verschillende andere manieren beschreven in eerdere antwoorden met behulp van een code. Naar mijn mening zijn deze wegen gemakkelijk om te onthouden en snel te schrijven.


Antwoord 10, Autoriteit 4%

De eenvoudigste manier om het te doen is:

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

Antwoord 11, Autoriteit 3%

Ik bouw mijn eigen oplossing met va_arg. Deze oplossing is C++ 98-compatibel.

#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


Antwoord 12, autoriteit 3%

Als uw compiler Variadic-macro’sondersteunt (wat geldt voor de meeste moderne compilers), kan de volgende macro gebruiken om vectorinitialisatie om te zetten in een oneliner:

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

Met deze macro kun je een geïnitialiseerde vector definiëren met de volgende code:

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

Dit zou een nieuwe vector van ints creëren met de naam my_vector met de elementen 1, 2, 3, 4.


Antwoord 13, autoriteit 2%

Als je Boost niet wilt gebruiken, maar van syntaxis wilt genieten, zoals

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

voeg gewoon dit stukje code toe

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

Antwoord 14, autoriteit 2%

In C++11:

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

Antwoord 15, autoriteit 2%

Een recentere dubbele vraag heeft dit antwoordvan Viktor Sehr. Voor mij is het compact, visueel aantrekkelijk (het lijkt erop dat je de waarden erin schuift), vereist geen C++11of een module van derden, en vermijdt het gebruik van een extra (geschreven) variabele. Hieronder is hoe ik het gebruik met een paar wijzigingen. In de toekomst kan ik overschakelen naar het uitbreiden van de functie van vector en/of 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)

Antwoord 16, autoriteit 2%

Je kunt dat doen met boost::assign:

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

Details vindt u hier.


Antwoord 17

De onderstaande methoden kunnen worden gebruikt om de vector in C++ te initialiseren.

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

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

De derde is alleen toegestaan in C++11en later.


Antwoord 18

Er zijn hier veel goede antwoorden, maar aangezien ik onafhankelijk tot mijn eigen kwam voordat ik dit las, dacht ik dat ik de mijne toch maar hier zou gooien…

Hier is een methode die ik hiervoor gebruik en die universeel zal werken op alle compilers en platforms:

Maak een struct of klasse als container voor uw verzameling objecten. Definieer een operator-overbelastingsfunctie voor <<.

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

U kunt functies maken die uw struct als parameter nemen, bijvoorbeeld:

someFunc( MyObjectList &objects );

Dan kun je die functie als volgt aanroepen:

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

Op die manier kunt u een verzameling objecten van dynamisch formaat bouwen en doorgeven aan een functie in één enkele strakke regel!


Antwoord 19

Als je iets wilt in dezelfde algemene volgorde als Boost::assign zonder een afhankelijkheid van Boost te creëren, is het volgende op zijn minst vaag vergelijkbaar:

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

Hoewel ik wou dat de syntaxis voor het gebruik ervan schoner was, is het nog steeds niet bijzonder verschrikkelijk:

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

Antwoord 20

typedef std::vector<int> arr;
arr a {10, 20, 30};       // This would be how you initialize while defining

Gebruik voor compileren:

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

Antwoord 21

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

Antwoord 22

Als de array is:

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 

Antwoord 23

Het is best handig om een vector inline te maken zonder variabele te definiëren tijdens het schrijven van een test, bijvoorbeeld:

assert(MyFunction() == std::vector<int>{1, 3, 4}); // <- this.

Antwoord 24

“Hoe maak ik een STL-vector en initialiseer ik deze zoals hierboven beschreven? Wat is de beste manier om dit te doen met minimale typinspanning?”

De gemakkelijkste manier om een vector te initialiseren terwijl u uw ingebouwde array heeft geïnitialiseerd, is door een initialisatielijst die werd geïntroduceerd in C++11te gebruiken.

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

ivecis 3 elementen groot nadat Assigning (gelabelde instructie) is uitgevoerd.


Antwoord 25

Er zijn verschillende manieren om een vector hard te coderen. Ik zal een paar manieren delen:

  1. Initialiseren door waarden één voor één te pushen

    // Create an empty vector
    vector<int> vect;
    vect.push_back(10);
    vect.push_back(20);
    vect.push_back(30);
    
  2. Initialiseren van soortgelijke arrays

    vector<int> vect{ 10, 20, 30 };
    
  3. Initialiseren vanuit een array

    int arr[] = { 10, 20, 30 };
    int n = sizeof(arr) / sizeof(arr[0]);
    vector<int> vect(arr, arr + n);
    
  4. Initialiseren vanuit een andere vector

    vector<int> vect1{ 10, 20, 30 };
    vector<int> vect2(vect1.begin(), vect1.end());
    

Antwoord 26

gerelateerd, u kunt het volgende gebruiken als u een vector volledig klaar wilt hebben om in een snelle verklaring te gaan (b.v. onmiddellijk doorgegeven aan een andere functie):

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

Voorbeeldfunctie

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

Voorbeeld Gebruik

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

Wees echter voorzichtig met het verklaring, zorg ervoor dat de eerste waarde duidelijk is wat u wilt.


Antwoord 27

b. Stroustrup beschrijft een leuke manier om operaties in 16.2.10 Selfreference op pagina 464 in de C++ 11-editie van de PROG. Lang. Wanneer een functie een referentie retourneert, aangepast aan een vector. Op deze manier kunt u keten als v.pb(1).pb(2).pb(3);maar kan te veel werk zijn voor dergelijke kleine winsten.

#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


Antwoord 28

De eenvoudigste, ergonomische manier (met C++ 11 of hoger):

auto my_ints = {1,2,3};

Antwoord 29

Als je het in je eigen klas wilt hebben:

#include <initializer_list>
Vector<Type>::Vector(std::initializer_list<Type> init_list) : _size(init_list.size()),
_capacity(_size),
_data(new Type[_size])
{
    int idx = 0;
    for (auto it = init_list.begin(); it != init_list.end(); ++it)
        _data[idx++] = *it;
}

Other episodes