ハードコードされた要素でstd :: vectorを初期化する最も簡単な方法は何ですか?


612

配列を作成して、次のように初期化できます。

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

std::vector同様にエレガントなを作成して初期化するにはどうすればよいですか?

私が知る最良の方法は:

std::vector<int> ints;

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

もっと良い方法はありますか?


1
初期化後にintのサイズを変更しない場合は、tr1配列の使用を検討してください。
zr。

@zr、あなたは私に好奇心を持っています...もし私が固定サイズを必要とするなら、私は普通の古い配列自体を使うことができませんか?今すぐtr1アレイを確認しています...
Agnel Kurian、

2
tr1::array通常の配列はSTLコンテナーのインターフェイスを提供しないため、便利です
Manuel

これを明示的にC ++ 03の質問にするためにタイトルを変更しました。新しい標準C ++で意味をなすようにすべての答えを調べて修正するよりも簡単に思えました。
TED

回答:


548

1つの方法は、配列を使用してベクトルを初期化することです。

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

7
それはせずに罰金を動作します@Agnel staticまたはconstただし、どちらもそれが使用され、コンパイラは追加の最適化を行うことができすべきかのようにそれがより明確にします。
ヤコビー

68
私はこれを否定しなかったが、私は誘惑された。これは主に、初期化された配列を最初から使用するだけでほとんど何も節約できないためです。しかし、それは実際にはC ++のせいであり、あなたのせいではありません。
TED

2
vecベクトルを定義するときにこれらのパラメーターを使用する理由を説明できますか?
DomX23 2012年

13
sizeof(array)は、配列の要素の合計サイズを取得できるいくつかの例外の1つであり、arrポインタの次元ではありません。つまり、基本的に彼はvector(pointer_to_first_element、pointer_to_first_element + size_in_bytes_of_the_whole_array / size_of_one_element)を使用しています:vector(pointer_to_first_element、pointer_after_final_element)。タイプはすでに<int>で指定されているので、ベクターは1つの要素の量を認識しています。イテレーターはポインターとして扱うことができるので、基本的にはvector(iterator begin、iterator end)コンストラクターを使用していることに注意してください
Johnny Pauling

11
@TED:場合によっては、結果のベクトルを変更する必要があります。たとえば、常にいくつかのデフォルトパラメータを用意し、いくつかのパラメータをカスタマイズして追加する必要がある場合があります。
DarkWanderer 2014

642

コンパイラがC ++ 11をサポートしている場合は、次のようにするだけです。

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

これは、バージョン4.4以降の GCCで使用できます。残念ながら、VC ++ 2010はこの点で遅れているようです。

または、Boost.Assignライブラリは非マクロマジックを使用して以下を許可します。

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

または:

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

ただし、これにはある程度のオーバーヘッド(基本的には内部でのlist_of構成std::deque)があるため、パフォーマンスが重要なコードの場合は、Yacobyが言うように実行するほうがよいことに注意してください。


ベクトルはセルフサイズなので、空に初期化してもいいですか?コンストラクタのように:this->vect = {};
Azurespot 2018年

3
@Azurespot初期化するだけで空になります:std::vector<T> vector;
ルーク

2
誰かが気std::vector<int> v = {1, 2, 3, 4};になるかもしれない場合に備えて、ベクトルinitializer list constructorはこのような初期化のために呼び出されます、そのドキュメントはC++ 11セクションで見つけることができます。
simomo

103

可能であれば、最新のC ++ [11,14,17、...]の方法を使用します。

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

可変長配列をループしたり使用したりする古い方法はsizeof()、目にはひどいものであり、精神的なオーバーヘッドの点で完全に不要です。ああ。


2
公平に言えば、これはもともとC ++ 03の質問でしたが、人々や企業が新しい標準を採用することを望みます。C ++では、EigenとBoostで利用できるものと同様に、標準ライブラリに可変長配列(VLA)の実装が必要です。
アダムエリクソン2018

残念ながら、このアプローチは、open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#1467など、場合によっては問題があります。ああ。
にオービットでライトネスレース

「同じタイプのオブジェクトからの集合体のリスト初期化」があなたの問題である場合、おそらくコードベースにもっと大きな問題があるでしょう...デバッグの問題を正当化するようなアプリケーションは考えられません。
アダムエリクソン

77

C ++ 0xでは、配列で行ったのと同じ方法でそれを行うことができますが、現在の標準ではできません。

言語サポートのみで使用できます:

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

他のライブラリを追加できる場合は、boost :: assignmentを試すことができます。

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

配列のサイズをハードコーディングしないようにするには:

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

もちろん、反対投票はしませんでしたが、とにかく質問があります。いつ配列のサイズがコンパイル時定数ではないのですか?つまり、3番目のものではなく2番目のスニペットで最初のソリューションを使用するのはどの場合ですか。
マヌエル

4
@Manuel、配列のサイズは型の一部であり、したがってコンパイル時定数です。現在、オプション1では、そのコンパイル時定数「N」を関数の戻り値として使用しています。関数の戻り値は、おそらく呼び出しの場所で定数値としてインライン化される場合でも、コンパイル時ではなく実行時の値です。違いは、次のことはできないというint another[size_of_array(array)]ことですint another[ARRAY_SIZE(array)]
DavidRodríguez-

1
オプション3では、「宣言済み、未定義」とはどういう意味なのかわかりません。したがって、変数は追加のメモリを使用しませんか?
To1ne

1
@ To1neは実際には変数ではなく関数宣言です。それを定義または定義する理由は、実際にsizeofは、定義を必要としない式以外の機能を必要としないためです。実際に定義を提供することはできますが、正しく行うには、配列の静的割り当てとそれへの参照を返す必要があります。次の質問は、配列の値として何が意味があるのでしょうか。(これは、関数のインスタンス化のタイプ/サイズの組み合わせごとに1つの配列を意味することにも注意してください!)の使用は賢明ではないので、避けたいと思います。
DavidRodríguez-

1
@mhd:言語で空の配列を作成することはできません。「int arr [0] = {};」有効なC ++コードではありません。しかし、空のベクトルと空でないベクトルを初期化したい場合は、異なる構成を使用する必要があるというのはあなたの言う通りです。C ++ 11ので、これを使用すると、初期化子リストのコンストラクタ使用できるように、非問題です
dribeas -デビッド・ロドリゲス

61

C ++ 11の場合:

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

ブーストlist_ofの使用:

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

ブースト割り当ての使用:

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

従来のSTL:

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

一般的なマクロを使用する従来のSTL:

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

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

2
C ++ 11 は配列std::beginstd::end配列もサポートしているため、ベクトルものように初期化できますstatic const int arr[] = {10,20,30}; vector<int> vec(begin(arr), end(arr));
Jaege、2016

54

私は自分の0.02ドルを投げると思っただけです。私はこれを宣言する傾向があります:

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

ユーティリティヘッダーのどこかにあり、必要なのは次のとおりです。

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

しかし、C ++ 0xが待ちきれません。私のコードもVisual Studioでコンパイルする必要があるため、行き詰まっています。ブー。


1
この手法は、型付きサイズの配列を受け入れる関数をオーバーロードするためにも使用できます。
Andres Riofrio 2012年

4
そのconst T (&data)[N]部分を説明できますか?あなたの呼び出しで配列のサイズはどのように推定されますmakeVector(values)か?
Patryk 2015年

36

C ++ 11より前:

方法1 =>

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

方法2 =>

 v.push_back(SomeValue);

以下のC ++ 11以降も可能です

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

28

で始まります:

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

C ++ 11コンパイラがなく、ブーストを使用したくない場合:

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

C ++ 11コンパイラがなく、ブーストを使用できる場合:

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

C ++ 11コンパイラがある場合:

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

22

ベクトルの初期化-

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

c ++ 11コンパイラがあれば実行できます。

それ以外の場合は、データの配列を作成してから、forループを使用できます。

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

これらとは別に、いくつかのコードを使用して、上記の他のさまざまな方法があります。私の意見では、これらの方法は覚えやすく、すばやく書くことができます。



16

を使用して独自のソリューションを構築しva_argます。このソリューションはC ++ 98に準拠しています。

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

デモ


14

コンパイラがVariadicマクロをサポートしている場合(ほとんどの最新のコンパイラに当てはまります)、次のマクロを使用して、ベクトルの初期化を1行に変換できます。

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

このマクロを使用すると、次のようなコードで初期化されたベクトルを定義できます。

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

これにより、要素1、2、3、4を持つmy_vectorという名前のintの新しいベクトルが作成されます。


13

ブーストを使用したくないが、次のような構文を楽しみたい場合

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

このコードのチャンクを含めるだけです

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

1
このコードの使い方を理解することはできませんでしたが、面白そうです。
Daniel Buckmaster

上記のコメントの1つが言ったようです。+ =とカンマ演算子をオーバーロードするだけです。わかりやすくするためにかっこを付ける:((((v+=1),2),3),4),5) これが機能する方法です。最初にvector<T> += Tvector_inserterを返します。vi元のベクターをカプセル化するベクターを呼び出してvi,Tから、Tを元のベクターに追加して、カプセル化してそれを返し、もう一度vi実行できるようにvi,Tします。
Piti Ongmongkolkul 2012

このコードはgcc 4.2.1では正しく機能しませんでした。+ =演算子内のローカル変数への参照を返すためと思いますが、アイデアは優れています。コードを編集すると、もう1つのコピーコンストラクターが表示されます。フローは-> + =-> ctor->コンマ->コピー-> dtor->コンマ......->コンマ-> dtorになりました。
Yevhen

私はおそらく+ =の代わりに<<をオーバーロードしたでしょう。少なくとも<<には、ビットシフトとcoutのために、あいまいな副作用のルールがあります
Speed8ump

11

C ++ 11の場合:

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

21
すでにC ++ 11を使用している場合は、直接的なアプローチを使用することもできます- vector<int> arr = {10, 20, 30};
Bernhard Barker

実際、私はint [](一部のC lib)を受け取り、ベクター(C ++ lib)にプッシュしたかった。この答えは役に立ちました、残りはしませんでした;-)
星雲

10

あなたはboost :: assignを使用してそれを行うことができます。

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

詳細はこちら


19
オペレーターが虐待をオーバーロードするという最悪のケースは長い間見ていません。い+=1,2,3,4であり、タックは、値の終わりに..またはそれがない追加 MATLAB-でこのはずのような構文として(第三の要素に第二要素、3に第一要素、2に1を言語のように)
bobobobo 2013年

10

最近の重複した質問には、Viktor Sehrによるこの回答があります。私にとって、それはコンパクトで視覚的に魅力的で(値を「押し付けている」ように見えます)、c ++ 11やサードパーティのモジュールを必要とせず、追加の(書き込まれた)変数の使用を避けます。以下は、いくつかの変更を加えた使用方法です。将来、vectorや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)

7

以下のメソッドを使用して、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); 等々

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

3番目のものは、C ++ 11以降でのみ使用できます。


5

ここには良い答えがたくさんありますが、私はこれを読む前に自分で自分自身にたどり着いたので、私はとにかくここに私を投げ捨てると思いました...

これは私がこれのために使用している方法であり、コンパイラとプラットフォーム全体で普遍的に機能します:

オブジェクトのコレクションのコンテナとして構造体またはクラスを作成します。<<の演算子オーバーロード関数を定義します。

class MyObject;

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

構造体をパラメーターとして使用する関数を作成できます。例:

someFunc( MyObjectList &objects );

次に、この関数を次のように呼び出すことができます。

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

このようにして、動的にサイズ設定されたオブジェクトのコレクションを作成し、1つのクリーンな行で関数に渡すことができます。


4

Boostへの依存関係を作成せずにBoost :: assignと同じ一般的な順序で何かが必要な場合、以下は少なくとも漠然と類似しています。

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

私はそれを使用するための構文がよりきれいであることを望みますが、それでもまだそれほどひどくはありません:

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

4
typedef std::vector<int> arr;

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

コンパイルするには:

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

質問はC ++ 03(11ではない)と述べています
Mike P

1
私がこれに答えたとき、それは03を指定しなかったと思います。しかし、完全に覚えてはいけません。しかし、それは簡単な解決策を探している人にとってはまだ有用な答えです。
shaveenk 2014

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

4

配列が次の場合:

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

テストを書くとき、変数を定義せずにインラインでベクトルを作成するのはかなり便利です。例えば:

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

3

関連して、クイックステートメントで完全に準備ができているベクトルが必要な場合(たとえば、すぐに別の関数に渡される場合)は、次を使用できます。

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

関数の例

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

使用例

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

decltypeに注意してください。ただし、最初の値が目的の値であることを確認してください。


3

ベクトルをハードコードするにはさまざまな方法があります。いくつかの方法を紹介します。

  1. 値を1つずつプッシュして初期化する
// Create an empty vector 
    vector<int> vect;  

    vect.push_back(10); 
    vect.push_back(20); 
    vect.push_back(30); 
  1. 配列のような初期化
vector<int> vect{ 10, 20, 30 };
  1. 配列からの初期化
    int arr[] = { 10, 20, 30 }; 
    int n = sizeof(arr) / sizeof(arr[0]); 

    vector<int> vect(arr, arr + n); 
  1. 別のベクトルからの初期化
    vector<int> vect1{ 10, 20, 30 }; 

    vector<int> vect2(vect1.begin(), vect1.end()); 

2

「STLベクトルを作成して上記のように初期化するにはどうすればよいですか?最小限のタイピング作業でこれを行うための最良の方法は何ですか?」

組み込み配列を初期化したときにベクトルを初期化する最も簡単な方法は、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は、Assigning(ラベル付きステートメント)が実行された後のサイズが3要素です。


同様の行で、マップを初期化しようとしています。std:: map <int、bool> catinfo = {{1、false}}; しかし、その後、このエラーエラーが発生します。C++ 98では、「catinfo」は「{...}」ではなく、コンストラクターによって初期化する必要があります
pdk

2

B. Stroustrup は、ProgのC ++ 11エディションの464ページの16.2.10自己参照で操作をチェーンするための優れた方法を説明しています。ラング。ここで関数は参照を返しますが、ここではベクトルに変更されています。この方法では、次のように連鎖できますがv.pb(1).pb(2).pb(3);、そのような小さな利益にはあまりにも多くの作業になる可能性があります。

#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


アルマジロライブラリは、行列の初期化のためにこれを行いますが、代わりに指定された関数の<<演算子を使用しています。arma.sourceforge.net/docs.html#element_initialisation
Agnel Kurian氏

0

最も簡単で人間工学的な方法(C ++ 11以降を使用):

auto my_ints = {1,2,3};

0

自分のクラスに入れたい場合:

#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;
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.