9

メモリ操作なしでC++およびSTLで2D配列を定義するには、いくつかの方法があります。次のコードは、2つの異なる方法を示しています。

int main () 
{
    /**************
        1   2   3
        4   5   6
    ***************/
    // Method 1
    const int ROW = 2;
    const int COL = 3;
    int array1[ROW][COL];
    for(int i=0; i<ROW; i++)
        for(int j=0; j<COL; j++)
            array1[i][j] = i*COL+j+1;

    // Method 2
    typedef vector<vector<int> > ARRAY; 
    ARRAY array2;
    vector<int> rowvector;
    for(int i=0; i<ROW; i++)
    {
        rowvector.clear();
        for(int j=0; j<COL; j++)
            rowvector.push_back(i*COL+j+1);
        array2.push_back(rowvector);
    }
    return 0;
}

私の質問は、2D配列を定義する他の方法はありますか?どれが最も効率的ですか?ありがとう!

4

8 に答える 8

19

C ++ 11では以下を使用しますstd::array

  std::array<std::array<int,3>,2> a {{
    {{1,2,3}},
    {{4,5,6}}
 }};

いくつかの使用法:

  a[0][2] = 13;
于 2012-10-11T16:29:26.490 に答える
6

ここには多くのトレードオフがあります。

Cスタイルの2D配列を宣言すると、int array[height][width]実際には1つの連続したメモリブロックが得られます。コンパイラはインデックスを1Dアドレスに変換します

array[row][col] == *(array + row * width + col)
  • 利点:キャッシュコヒーレンシ。すべてのメモリは同じ場所にあります。
  • 短所:すべてのインデックス作成に乗算が必要です。間接参照の方が速い場合があります。

のを使用するvectorvectors、各行が個別に割り当てられます。アウターvectorはインナーへのポインターを格納しますvectors。インデックス付けは間接参照になり、その後に追加が続きます。

array[row][col] == *(*(array + row) + col)
  • 利点:間接化は乗算よりも高速である可能性があります。
  • 短所:各行が個別に割り当てられるため、キャッシュコヒーレントではありません(実装がに最適化されている場合を除くvector<vector>)。

パフォーマンスが本当に重要な場合は、両方をテストして、データでどちらが速いかを判断する必要があります。

于 2012-10-11T14:01:00.987 に答える
6

一般的なパターンは、適切なインターフェイスを提供するクラス内に2D配列をカプセル化することです。その場合、たとえばrows*cols要素の単一のベクトルなど、他の内部表現を使用できます。インターフェイス(通常operator()(int,int)、呼び出し元からの座標を線形ベクトル内の位置にマップします。

利点は、動的割り当てがありますが、単一の割り当て(std::vector<std::vector<int>>各ベクトルが独自のメモリを取得する必要がある場所とは異なります)と、データの局所性を提供する単一のブロックにあることです。

于 2012-10-11T14:25:47.593 に答える
6

配列を定義する非常に効率的な方法の1つは、newanddelete演算子を使用した動的割り当てです。次に例を示します。

int **arr=new int*[ROW];
for( int i=0; i<ROW; ++i ) {
  arr[i] = new int[COL];
  for( int j=0; j<COL; ++j ) {
    arr[i][j] = some_val;
  }
}

このアプローチの大きな利点は、アレイが使用するメモリが不要になったときに、簡単に削除できることです。2D配列を削除する例を次に示します。

for( int i=0; i<ROW; ++i ) {
  delete[] arr[i];
}
delete[] arr;   
于 2012-10-11T16:38:31.287 に答える
4

2D配列を定義する他の方法はありますか?

明示的にメモリを操作せずにいいえ(malloc / free)。静的に割り当てられた配列(最初の例)を使用する場合、コンパイル時にスペースを割り当てるため、実行時に行または列を追加することはできません。

2番目の例ではstd::vector、動的メモリ割り当てを非表示にしています。このようにして、最終的に実行時に行または列を追加できます。

配列の次元を動的に変更する必要がない場合、最初の解決策はより単純で高速なものです(std :: vectorの実装は静的配列に匹敵するほど高速で、よりエレガントでオブジェクト指向であると思いますが) )。

実行時に配列の次元を変更する必要がある場合は、std :: vectorを使用してください。これにより、mallocやfreeを直接処理する必要がなくなります。

于 2012-10-11T13:54:52.203 に答える
4

を使用して2D配列を宣言するにはstd::vector、次の種類の構造を使用できます。

vector<vector<int> >  matrix( n, vector<int>(m, -1) );

これにより、すべての要素がに初期化された、matrixサイズの2D配列が作成されます。nm-1

これは基本的に、「値の項目で初期化する」nvalコンストラクターのネストです。

vector (size_type n, const value_type& val,
                 const allocator_type& alloc = allocator_type());

(ここからコピーされたコンストラクター定義)

于 2014-01-10T04:48:41.320 に答える
0

事前に要素を知っているなら、あなたはただすることができます

int arr [2] [3] = {{1,2、3}、{4、5、6}};

これは、method1およびmethod2よりも効率的であるはずです。ベクトルを使用すると、自分でメモリ操作を行うことはありませんが、ベクトルの実装では、動的に割り当てられた配列を使用する可能性があります。

于 2012-10-11T14:08:16.867 に答える
-1

このベクトルのようなものができます>m_2DArray;

次に、行数(行)と列数(列)がわかれば、2次元配列のサイズを変更できます。

m_2DArray.resize(rows);

for(auto&el:m_2DArray)el.resize(columns);

他の2D配列と同様に、m_2DArray[i][j]を使用して2D配列のデータにアクセスできます。

于 2020-04-09T19:29:04.087 に答える