2

この配列の場合:

vector<vector<int> > v;

v.push_back(vector<int>(0));
v.back().push_back(1);
v.back().push_back(2);
v.back().push_back(3);
v.back().push_back(4);

{1, 2, 3, 4} を簡単に出力できます。

cout << v[0][0] << endl;
cout << v[0][1] << endl;
cout << v[0][2] << endl;
cout << v[0][3] << endl;

フラット配列としてアクセスするには、次のようにします。

int* z = (int*)&v[0].front();

cout << z[0] << endl;
cout << z[1] << endl;
cout << z[2] << endl;
cout << z[3] << endl;

では、多次元ベクトルにフラットな多次元配列としてアクセスするにはどうすればよいでしょうか? 1 次元ベクトルにアクセスするのと同じ形式は使用できません。

// This does not work (outputs garbage)
int** n = (int**)&v.front();

cout << n[0][0] << endl;
cout << n[0][1] << endl;
cout << n[0][2] << endl;
cout << n[0][3] << endl;

私が見つけた回避策は、これを行うことです:

int** n = new int* [v.size()];

for (size_t i = 0; i < v.size(); i++) {
   n[i] = &v.at(i).front();
}

cout << n[0][0] << endl;
cout << n[0][1] << endl;
cout << n[0][2] << endl;
cout << n[0][3] << endl;

アクセスする前にデータの上に各次元を動的に割り当てることなく、フラットな C スタイル配列のような多次元ベクトル全体にアクセスする方法はありますか?

実装において速度は重要ではなく、メンテナンスの明確さが最も重要です。多次元ベクトルは、データを格納するのに最適です。ただし、他の言語から簡単にアクセスできるように、SDK でフラットな C スタイルの配列としてデータを公開することも必要です。つまり、ベクトルを STL オブジェクトとして公開することはできません。

私が思いついた解決策は、処理の最後に一度だけ配列を評価して「平坦化」するため、私のニーズにはうまく機能します。しかし、これについてもっと良い方法はありますか?それとも、独自のデータ構造を再実装せずに、可能な限り最善の方法ですでにそれを行っていますか (フラット化されたコードは数行しかないため、やり過ぎです)。

友達、アドバイスありがとう!

4

4 に答える 4

3

Avectorのバッファは、一般に動的に割り当てられます。

つまり、vectorofがある場合vector、内部バッファーに関しては、ポインターの配列に似たものがあり、各ポインターは配列を指しています。

同じデータの 1D ビューと 2D ビューを切り替える必要がある場合、おそらく最も簡単なのは、次のように 2D 配列クラスを定義することです (簡単に説明します)。

typedef ptrdiff_t Size;
typedef Size Index;

template< class Item >
class Array2D
{
private:
    std::vector< Item > items_;
    Size                width_;
    Size                height_;

    Index indexFor( Index const x, Index const y )
    { return y*width_ + x; }

public:
    Size width() const { return width_; }
    Size height() const { return height_; }

    Item& operator()( Index const x, Index const y )
    { return items_[indexFor( x, y )]; }

    Item const& operator()( Index const x, Index const y ) const
    { return items_[indexFor( x, y )]M; }

    Size bufferSize() const { return width_*height_; }
    Item* buffer() { return &items_[0]; }
    Item const* buffer() const { return &items_[0]; }

    Array2D( Size const w, Size const h )
        : items_( w*h )
        , width_( w )
        , height_( h )
    {}
};

次に、次のようなことができます

Array2D< int >  a( 4, 3 );

for( Index y = 0;  y < a.height();  ++y )
{
    for( Index x = 0;  x < a.width();  ++x )
    {
        foo( a( x, y ) );
    }
}

Array2D< int >  a( 4, 3 );

int* const pb = a.buffer();
for( Index i = 0;  i < a.bufferSize();  ++i )
{
    foo( pb[i];
}
于 2012-10-20T23:08:43.873 に答える
0

では、多次元ベクトルにフラットな多次元配列としてアクセスするにはどうすればよいでしょうか?

できません。

vector<int>そのままアクセスできるのint[]は、レイアウトが同じだからです。のメモリ レイアウトは のレイアウトとvector<vector<int>>は異なりint*[]ます。つまり、 のようにアクセスすることはできませんint*[]

を介してデータにアクセスすることを避けられない場合はint*[]、 の配列を割り当ててint*、ベクトルへのポインターを設定することが最善の方法です。ただし、そもそもこれを行う必要がないようにできればよいでしょう。

に対して例外セーフ ホルダーを使用することをお勧めしますint*[]。また、おそらく使用する必要はなくvector::at()、ベクトルの 1 つが空の場合を処理する必要があるかどうかを検討することもできます。ここでは、C++11 の機能を使用してこれらの問題に対処します。

std::unique_ptr<int*[]> n(new int* [v.size()]);
transform(begin(v), end(v), n.get(), [](std::vector<int> &i) { return i.data(); });
于 2012-10-20T23:00:32.783 に答える
0

ベクトルはその要素を連続メモリに格納することが保証されていますが、ベクトルのベクトルは 2D C スタイル配列と同じストレージ レイアウトを保証していないためです。

int* z = (int*)&v[0].front();いいえ、それは不可能です。さらに進んで、それは単なる醜いことだと言えます。

于 2012-10-20T23:00:50.330 に答える
0

1d ベクトル ( std::vector<int>) が同じサイズの場合、ベクトルの生の配列を保持します。

typedef int ARRAY[6];
std::vector<ARRAY> yourVector; 

それらのサイズが同一でない場合、それぞれstd::vector<int>が連続したメモリ領域を占有しているため、実際の問題がありますが、これらの領域は連続していません。この生の C 配列とまったく同じです。

int** a = new int*[3];
a[0] = new int[4];
a[1] = new int[5];

aサイズの連続したメモリを指していません(4+5)*sizeof(int)...

于 2012-10-20T23:01:21.377 に答える