[英]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.