簡體   English   中英

快速將雙指針數組轉換為單指針,可能是連續的

[英]Fast convert double pointer array into single pointer, probably can be continuous

我正在使用一個將圖像作為大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
        }

    }

看起來row和cols的值是已知的。

因此, 第二個問題是:我可以修改此代碼以使其在一個內存塊中分配2D數組:

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

然后允許我以某種方式將其映射到我的一維數組而無需復制內存?


編輯:感謝@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;

那么第一個問題是,我是否可以在這里做得更好?

您可以使用std::vector使內存管理更安全,更簡單。 我認為沒有什么可以改善的地方。

問題是我需要將int *發送到另一個對象(OpenCV Mat構造函數)中,因此我只能使用那些類型。 不管怎么說,還是要謝謝你!

這不是問題。 您可以使用vector的data成員函數,該函數返回指向內部數組的指針,該指針可以發送到另一個項目中。


因此,第二個問題是:我可以修改此代碼以使其在一個內存塊中分配2D數組:

我假設您已綁定到需要傳遞int**的接口。

如果您可以接受兩種分配,那很簡單:首先分配適當大小的指針數組。 然后分配一個包含所有值的平面數組,並將其分配給指針數組的第一個元素。 然后,將其余的指針分配給值數組的正確位置。

單個分配是可能的,但很棘手。 您可以為指針數組和值數組分配足夠大的原始char數組,並使用new位置進行構造。 這很棘手,因為它的級別很低,您必須確保數組正確對齊,並且必須分配額外的空間才能對齊。 這將更容易在具有aligned_alloc C中aligned_alloc (似乎也將在即將發布的C ++ 17中實現)。


在庫代碼中銷毀它的正確方法似乎是

 delete ptr; delete labels; 

不,這似乎是錯誤的方式。 刪除分配給new[]內存的正確方法是delete[]

通過使用指針算術而不是數組訪問,您可能會有所改進。

我們可以使用指針來跟蹤源和目標,並在循環的每次通過中增加它們,這樣我們就可以保存乘法。 對每個涉及的指針執行此操作還具有消除對變量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的原始代碼中獲得像這樣的代碼,我不會感到驚訝。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM