2016-12-28 4 views
2

私は大きい2D配列int**としてイメージを返すライブラリを使用しています。私はint* 1D配列に変換する必要があります。私は、メモリ・ブロックをコピーすることによって、かなり速いそれを行うことができたと思う:ダブルポインタ配列を単一ポインタに高速変換すると、おそらく連続している可能性があります

// have int labels** as 2D array, also have rows and cols 

//create 1D array 
int *labels1D = new int[rows*cols]; 

//copy contents 
for(int i = 0; i < rows; i++) {   
    // Here I don't know anything about how those arrays were allocated 
    // Maybe std::copy would handle it for me? 
    std::copy_n(labels[i], cols, labels1D + i*cols); 
} 

ので最初の質問が、私はここに、より良い何かを行うことができるかどうかですか?図書館がブラックボックスであると仮定して、ここでは安全ですか?


私は、ライブラリのコードを変更することはあまりしたくないが、私はthis->currentLabels私の側ライブラリ内のソース列が作成されたさらにどのように見つけた:

int** currentLabels; //in class declaration 
... 
// in the code 
this->currentLabels = new int*[this->height]; 

for (int i = 0; i < this->height; ++i) { 
    this->currentLabels[i] = new int[this->width]; 

    for (int j = 0; j < this->width; ++j) { 
    // some code for setting the value 
     } 

    } 

は、行の値のように見えるとコラムは知られている。

ので2番目の質問は次のとおりです。私はそれが1つのメモリブロックに2次元配列を割り当てる作るためにこのコードを変更することができます。

this->currentLabels = malloc(nrows*sizeof(int*) + (nrows*(ncolumns*sizeof(int))); 

私はその後、ちょうどコピーせずに私の1Dアレイに何とかそれをマッピングできるようにしますメモリ?


EDIT:@SamVarshavchikのおかげで、マッピングは次のように動作しているようだ:

// Allocate 2-D array as one block: 

// Allocate pointers: 
int** labels = new int*[rows]; 
// Allocate data: 
auto ptr=new int[rows*cols]; 

for(int i = 0; i < rows; i++) { 
    labels[i] = &ptr[i*cols]; 
} 

// fill with values ranging 0 to certain number 
for(int i = 0; i < rows; i++){ 
    for(int j = 0; j < cols; j++){ 
     // the code for setting the values 
     labels[i][j] = i+j; 
    } 
}  

// have int labels** as 2D array, also have rows and cols 

//create 1D array 
int *labels1D; // = new int[rows*cols]; 

//assign contents: 
labels1D = &labels[0][0]; 

ライブラリのコードでそれを破壊するための正しい方法は

delete[] ptr; //user2079303 fixed 
delete[] labels; 
のようです
+2

はい、ライブラリコードを変更して1次元配列を割り当て、各行に別々にポインタの配列を割り当てることができます。しかし、ライブラリにはおそらくこの2次元配列の割り当てを解除しようとするコードがあります。それを見つけて同様の変更を加える必要があります。また、既存のライブラリコードは 'new'を使用しているので、' malloc'を使用する代わりに、それに固執してください。このユースケースでは、 'malloc'と' new'の間に究極の違いはありません。 –

+0

@SamVarshavchikありがとう、私はそれを行う方法を探していますが、私はそれを実装する方法を得ることができません。なぜなら、1次元配列のために、ポインタブロック 'nrows * sizeof(int *) ' – Slowpoke

+1

これは複雑ではありません。 1次元配列は 'auto ptr = new int [width * height]'として割り当てられ、行番号nへのポインタは '&ptr [n * width]'になります。かなり簡単。 –

答えて

3

最初の質問は私がここで何か良いことをすることができるかどうかです。

std::vectorを使用すると、メモリ管理をより安全で簡単に行うことができます。私は改善すべき点はそれほど多くありません。

問題は、別のオブジェクト(OpenCV Matコンストラクタ)にint *を送信する必要があることです。そのため、これらのタイプには限りがあります。とにかくありがとう!

これは問題ではありません。ベクトルdataのメンバー関数を使用して、別のプロジェクトに送信できる内部配列へのポインタを返します。


だから、2番目の質問です:私はそれが1つのメモリブロックに2次元配列を割り当てる作るためにこのコードを変更することができます。

私はあなたがインターフェイスにバインドされていると仮定していますあなたはint**を渡す必要があります。

2つの割り当てを受け入れることができれば簡単です。まず、適切なサイズのポインタの配列を割り当てます。次に、すべての値を含むフラット配列を割り当て、ポインタ配列の最初の要素に割り当てます。次に、残りのポインタを値配列の正しい位置に割り当てます。

1回の割り当ては可能ですが、トリッキーです。ポインタ配列と値配列の両方に十分な大きさの未加工のchar配列を割り当て、新しい配置で構築することができます。非常に低レベルであるため、これは扱いにくいので、配列が正しく整列されていることを確認し、整列を可能にするために余分なスペースを割り当てる必要があります。これはaligned_alloc(今後のC++ 17にもあるようです)のC言語で実装する方が簡単です。


ライブラリのコードでそれを破壊するための正しい方法はありません、それは間違った方法であるように思わ

delete ptr; 
delete labels; 

のようです。 new[]で割り当てられたメモリを削除する正しい方法はdelete[]です。

+0

問題は、別のオブジェクト(OpenCV Matコンストラクタ)に 'int *'を送る必要があるため、私はこれらの型には限りがあります。とにかくありがとう! – Slowpoke

+0

訂正ありがとう!私は誰かがそれを使用する場合にポストのコードを編集しました – Slowpoke

+1

@スローポーク - 型のベクトルを使うことができます。最初の要素へのポインタを渡します。 |ベクトル例(number_of_elements); | &example [0]を使用してint *が作成されます。 – rcgldr

1

配列アクセスではなくポインタ演算を使用すると、少し改善が得られるかもしれません。

ポインタを使用してソースとターゲットを追跡し、ループの各パスでポインタを増やして、乗算を保存することができます。関連する各ポインタでこれを行うことは、変数iの必要性を取り除くという利点も有し、変数iを含むすべての演算を保存し、終了ポインタを計算するだけでよい。また、不平等をチェックすることは、通常、「より小さい」比較よりも速い。

//create 1D array 
int *labels1D = new int[rows*cols]; 

//copy contents 
int *targetPointer = labels1D; 
int **sourcePointer = labels; 
int *endTargetPointer = targetPointer + rows*cols; 
while(targetPointer != endTargetPointer) {   
    std::copy_n(*sourcePointer++, cols, targetPointer); 
    targetPointer += cols; 
} 

一部オプティマイザはOPの元のコードから、このようなコードを取得することができれば、私は驚かないだろうけど。

+0

ありがとう!連続した配列を受け取るようにライブラリを修正することになったのですが、それは私と同じ問題を抱えている人にとっては役に立ちます – Slowpoke

関連する問題