ベクトルを配列に変換する方法


352

どのようにa std::vector<double>をa に変換しdouble array[]ますか?


9
ちょっと質問をする理由は?ベクトルには配列としてアクセスできます。配列はベクトルがしないことは何をしますか?
マイケルドーガン、

96
@Michael私の典型的な使用例は、自分のコードでベクトルを使用し、配列を取るサードパーティ関数を呼び出す必要がある
Michael Mrozek

7
使われている用語がわかりにくいです。ポインタは配列ではありません。配列の最初の要素または配列へのポインターが必要ですか?
GManNickG

7
絶対に本当の質問です。非常にシンプルで、簡単に解釈できます。再開してください。
dbliss

10
「金田はなぜ質問をするのか?」-まず、そのフレーズの誤用。第二に、その理由は明らかです。
ジムバルター2017

回答:


533

これを行うにはかなり簡単なトリックがあります。仕様では、ベクトルが要素を連続的に格納することが保証されているためです。

std::vector<double> v;
double* a = &v[0];

29
@ganukeコピーではなく、ベクターが内部で使用している実際の配列を指すポインターを作成しています。GManの回答をコピーしたい場合は、方法について説明します
Michael Mrozek

4
@ganuke:「配列」とは何ですか?詳細情報を提供する必要があります。全体像は何ですか?
GManNickG 2010年

6
@ganuke必要ありませんdouble*。同じデータを指すが必要です。この答えはまさにその場合に
当てはまります

6
ベクターは、そのメモリを所有している@guneykayim、あなたがそれを解放しないでください
マイケルMrozek

23
std::vector<double> v; double* a = v.data();
sinoTrinity 2015年

148

何のために?明確にする必要があります:配列の最初の要素または配列へのポインターが必要ですか?

前者を期待するAPI関数を呼び出す場合は、を実行できますdo_something(&v[0], v.size())。ここvで、はのベクトルですdouble。ベクトルの要素は連続しています。

それ以外の場合は、各要素をコピーするだけです。

double arr[100];
std::copy(v.begin(), v.end(), arr);

thar arrが十分に大きいだけでなく、arrいっぱいになるか、初期化されていない値があることを確認してください。


15
注:v.size()を使用して、新しい配列の要素数を取得します。double arr [v.size()];
rbaleksandar 2013

7
@rbaleksandar:配列に定数でない式のサイズを含めることはできません。
GManNickG 2013

@GManNickG:動作しますが、ここには誤解があると思います。次のことを想像してみてください。クラスを定義する時点では不明であり、後でさまざまなベクトルをフラッシュしてサイズパラメータを使用することで作成される、配列を指す必要があるさまざまなタイプの一連のポインタを持つクラスがあるとします。使用するスペースを決定します。別の例:サイズの関数パラメーターを使用して配列(短いarr [arrSize];)を作成する単純な関数void arrayTest(unsigned int arrSize)。
rbaleksandar 2013

1
@rbaleksandar誤解はありません。C ++ 11以前では、配列サイズは整数定数式でなければなりません。関数の例は、CでのVLAの一般的な使用法ですが、C ++の(非標準)拡張でのみサポートされています。ただし、C ++ 14に含まれる場合があります:stackoverflow.com/a/17318040/87234。しかし今のところ、それは単に標準的なオプションではありません。
GManNickG 2013

1
@GManNickG私は@Jetあなたは配列にベクトルを変換する場合と言っている、とあなたが使用してサイズに配列をつもりだと思うsize()の機能をstd:vector使用する必要がありますnewまたはmallocそれを行うに。すでに指摘されているように、これはdouble arr[v.size()]無効です。newの代わりにvectorを使用するのは良い考えですが、問題の核心は、どのようにしてvectorを配列に変換できるかです。
RyanP


17
vector<double> thevector;
//...
double *thearray = &thevector[0];

これは標準で動作することが保証されていますが、いくつかの警告があります。特に、が範囲内にあるthearrayときにのみ使用するように注意してthevectorください。


4
...そして、ベクターがでないことを確認してくださいempty()。そうでない場合、これは恐ろしいUBを呼び出します。
sbi

13

ベクトルは事実上、皮膚の下の配列です。関数がある場合:

void f( double a[]);

次のように呼び出すことができます:

vector <double> v;
v.push_back( 1.23 )
f( &v[0] );

ベクトルを実際の配列インスタンスに変換する必要はありません。


1
私はあなたf( &v[0] );があなたの最後のラインを意味したと思います
マイケル・ムロゼック

10

とおりstd::vector<int> vec取得するVEC、int*は、次の2つのメソッドを使用することができます。

  1. int * arr =&vec [0];

  2. int * arr = vec.data();

Tベクトルをに変換する場合はT* array、上記intをに置き換えTます。

よく理解するために、上記の2つがなぜ機能するのかを示します。

std::vector 動的配列です。

以下のメインデータメンバー:

template <class T, class Alloc = allocator<T>>
class vector{
    public:
        typedef T          value_type;
        typedef T*         iterator;
        typedef T*         pointer;
        //.......
    private:
        pointer start_;
        pointer finish_;
        pointer end_of_storage_;

    public:
        vector():start_(0), finish_(0), end_of_storage_(0){}
    //......
}

これrange (start_, end_of_storage_)は、ベクトルが割り当てるすべての配列メモリです。

range(start_, finish_)ベクターは、使用されるすべてのアレイのメモリです。

これrange(finish_, end_of_storage_)はバックアップアレイメモリです。

例えば、ベクトルvecについて。{9、9、1、2、3、4}を持つポインタは、以下のようなポインタです。

ここに画像の説明を入力してください

そう &vec[0] = start_(address。)(start_はint *配列の先頭と同じです)

ではメンバ関数だけSTART_を返しますc++11data()

pointer data()
{ 
     return start_; //(equivalent to `value_type*`, array head)
}

2

data()メソッドを使用してこれを行うことができます。C ++ 11はこのメソッドを提供します。

コードスニペット

#include<bits/stdc++.h>
using namespace std;


int main()
{
  ios::sync_with_stdio(false);

  vector<int>v = {7, 8, 9, 10, 11};
  int *arr = v.data();

  for(int i=0; i<v.size(); i++)
  {
    cout<<arr[i]<<" ";
  }

  return 0;
}


1

関数がある場合は、おそらくこれが必要ですfoo(&array[0], array.size());。配列が必要な状況になった場合は、リファクタリングする必要があります。ベクトルは基本的に拡張配列なので、常に使用する必要があります。


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