it-swarm.com.de

Was ist der einfachste Weg, um einen std :: vector mit fest codierten Elementen zu initialisieren?

Ich kann ein Array erstellen und es folgendermaßen initialisieren:

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

Wie erstelle ich einen std::vector und initialisiere ihn ähnlich elegant?

Der beste Weg, den ich kenne, ist:

std::vector<int> ints;

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

Gibt es einen besseren Weg?

567
Agnel Kurian

Eine Methode wäre, das Array zum Initialisieren des Vektors zu verwenden

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

Wenn Ihr Compiler C++ 11 unterstützt, können Sie einfach Folgendes tun:

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

Dies ist in GCC ab Version 4.4 verfügbar. Leider scheint VC++ 2010 in dieser Hinsicht hinterherzuhinken.

Alternativ verwendet die Bibliothek Boost.Assign Nicht-Makro-Magie, um Folgendes zu ermöglichen:

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

Oder:

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

Denken Sie jedoch daran, dass dies einen gewissen Overhead hat (im Grunde konstruiert list_of einen std::deque unter der Haube), sodass Sie für leistungskritischen Code besser dran sind, wie Yacoby sagt.

594
Manuel

In C++ 0x können Sie dies auf die gleiche Weise tun, wie Sie es mit einem Array getan haben, jedoch nicht im aktuellen Standard.

Mit nur Sprachunterstützung können Sie verwenden:

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

Wenn Sie andere Bibliotheken hinzufügen können, können Sie boost :: assign ausprobieren:

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

So vermeiden Sie die Hardcodierung der Größe eines Arrays:

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

Wenn du kannst, benutze die moderne C++ [11,14,17, ...] Methode:

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

Die alte Methode, ein Array mit variabler Länge zu durchlaufen oder sizeof() zu verwenden, ist für die Augen wirklich schrecklich und in Bezug auf den mentalen Aufwand völlig unnötig. Yuck.

75
Adam Erickson

In C++ 11:

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

Verwenden von boost list_of:

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

Boost Assign verwenden:

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

Konventionelle STL:

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

Konventionelle AWL mit generischen Makros:

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

Herkömmliche AWL mit einem Vektorinitialisierungsmakro:

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

Ich dachte nur, ich würde meine 0,02 $ einwerfen. Ich neige dazu, dies zu erklären:

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

in einem Utility-Header irgendwo und dann ist alles, was erforderlich ist:

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

Aber ich kann nicht auf C++ 0x warten. Ich stecke fest, weil mein Code auch in Visual Studio kompiliert werden muss. Boo.

52
M. Tibbits

Vor C++ 11:

Methode 1 =>

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

Methode 2 =>

 v.Push_back(SomeValue);

Ab C++ 11 ist dies ebenfalls möglich

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

Beginnen mit:

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

Wenn Sie keinen C++ 11-Compiler haben und boost nicht verwenden möchten:

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

Wenn Sie keinen C++ 11-Compiler haben und boost verwenden können:

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

Wenn Sie einen C++ 11-Compiler haben:

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

Der einfachste Weg ist:

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

Zur Vektorinitialisierung -

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

kann getan werden, wenn Sie C++ 11-Compiler haben.

Andernfalls können Sie ein Array der Daten haben und dann eine for-Schleife verwenden.

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

Abgesehen von diesen gibt es verschiedene andere Möglichkeiten, die oben unter Verwendung von Code beschrieben wurden. Meiner Meinung nach sind diese Wege leicht zu merken und schnell zu schreiben.

20
Tush_08

Wenn Ihr Compiler Variadic-Makros unterstützt (was für die meisten modernen Compiler zutrifft), können Sie mit dem folgenden Makro die Vektorinitialisierung in einen Einzeiler umwandeln:

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

Mit diesem Makro können Sie einen initialisierten Vektor mit folgendem Code definieren:

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

Dies würde einen neuen Vektor von ints mit dem Namen my_vector mit den Elementen 1, 2, 3, 4 erzeugen.

14
Matt Ball

In C++ 11:

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

Wenn Sie Boost nicht verwenden möchten, aber Syntax wie genießen möchten

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

fügen Sie einfach diesen Code ein

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

Ich baue meine eigene Lösung mit va_arg. Diese Lösung ist C++ 98-kompatibel.

#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

11
aloisdg

Eine neuere doppelte Frage hat diese Antwort von Viktor Sehr . Für mich ist es kompakt, optisch ansprechend (sieht aus, als würden Sie die Werte verschieben), erfordert kein C++ 11- oder Drittanbieter-Modul und vermeidet die Verwendung einer zusätzlichen (geschriebenen) Variablen. Unten ist, wie ich es mit ein paar Änderungen verwende. Ich werde möglicherweise in Zukunft die Funktion von vector und/oder va_arg erweitern.


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

sie können dies mit boost :: assign tun.

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

Detail hier

10
f4.

Die folgenden Methoden können verwendet werden, um den Vektor in c ++ zu initialisieren.

  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); und so weiter

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

Die dritte ist erst ab C++ 11 zulässig.

6
Jay
// 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.
5
sg7

Wenn Sie etwas in derselben allgemeinen Reihenfolge wie Boost :: assign haben möchten, ohne eine Abhängigkeit von Boost zu erstellen, ist Folgendes zumindest vage ähnlich:

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

Ich wünschte, die Syntax wäre sauberer, aber es ist nicht besonders schlimm:

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

Wenn das Array ist:

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 
4
FaridLU
typedef std::vector<int> arr;

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

Verwendung kompilieren:

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

Hier gibt es viele gute Antworten, aber da ich vor dem Lesen selbstständig zu meinen Antworten gekommen bin, habe ich mir gedacht, dass ich meine sowieso hier raufwerfen würde ...

Hier ist eine Methode, die ich dafür verwende und die universell auf Compilern und Plattformen funktioniert:

Erstellen Sie eine Struktur oder Klasse als Container für Ihre Sammlung von Objekten. Definieren Sie eine Operatorüberladungsfunktion für <<.

class MyObject;

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

Sie können Funktionen erstellen, die Ihre Struktur als Parameter verwenden, z.

someFunc( MyObjectList &objects );

Dann können Sie diese Funktion wie folgt aufrufen:

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

Auf diese Weise können Sie eine dynamisch bemessene Sammlung von Objekten in einer einzigen klaren Linie erstellen und an eine Funktion übergeben!

4
BuvinJ

Im Zusammenhang damit können Sie Folgendes verwenden, wenn Sie möchten, dass ein Vektor für eine Schnellanweisung vollständig bereit ist (z. B. umgehend an eine andere Funktion übergeben):

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

beispielfunktion

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

beispiel verwenden

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

achten Sie jedoch auf den Dekltyp, und stellen Sie sicher, dass der erste Wert eindeutig Ihren Wünschen entspricht.

3
Josh

B. Stroustrup beschreibt in 16.2.10 Selfreference auf Seite 464 in der C++ 11-Ausgabe des Prog eine nette Möglichkeit, Operationen zu verketten. Lang. Wenn eine Funktion eine Referenz zurückgibt, wird diese hier in einen Vektor geändert. Auf diese Weise können Sie wie v.pb(1).pb(2).pb(3); verketten, aber möglicherweise zu viel Arbeit für so kleine Gewinne leisten.

#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

2
kometen

"Wie erstelle ich einen STL-Vektor und initialisiere ihn wie oben beschrieben? Was ist der beste Weg, dies mit minimalem Schreibaufwand zu tun?"

Der einfachste Weg, einen Vektor zu initialisieren, während Sie Ihr eingebautes Array initialisiert haben, ist die Verwendung einer Initialisierungsliste , die in C++ 11 eingeführt wurde .

// 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 ist 3 Elemente groß, nachdem Assigning (Labeled Statement) ausgeführt wurde.

2
user2103487