将双指针数组快速转换为单指针,可能是连续的

时间:2016-12-28 23:35:20

标签: c++ arrays c++11

我正在使用一个库,它将图像作为一个大的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
        }

    }

看起来行和列的值是已知的。

所以第二个问题是:我可以修改此代码,使其在一个内存块中分配2D数组:

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

允许我然后将它以某种方式映射到我的1D阵列而不复制内存?

编辑:感谢@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 个答案:

答案 0 :(得分:3)

  

所以第一个问题是我能否在这里做得更好?

您可以使用std::vector使内存管理更安全,更简单。我没有看到其他改进措施。

  

问题在于我需要将int *发送到另一个对象(OpenCV Mat构造函数)中,因此我完全限制了这些类型。不管怎样,谢谢!

这不是问题。您可以使用vector的data成员函数,该函数返回指向您可以发送到另一个项目的内部数组的指针。

  

所以第二个问题是:我可以修改这段代码,使其在一个内存块中分配2D数组:

我假设您已经绑定了要求您传递int**的界面。

如果你可以接受两个分配,那很简单:首先分配适当大小的指针数组。然后分配包含所有值的平面数组,并将其分配给指针数组的第一个元素。然后将其余指针分配给值数组的正确位置。

单一分配是可能的,但很棘手。您可以为指针数组和值数组分配足够大的原始char数组,并使用placement new进行构造。这很棘手,因为它的级别非常低,并且必须确保阵列正确对齐,并且必须分配额外的空间以使对齐成为可能。这将更容易在具有aligned_alloc的C中实现(这似乎也在即将到来的C ++ 17中)。

  

在库代码中销毁它的正确方法似乎是

delete ptr;
delete labels;

不,这似乎是错误的方式。删除使用new[]分配的内存的正确方法是delete[]

答案 1 :(得分:1)

使用指针算法而不是数组访问可能会有一些改进。

我们可以使用指针来跟踪我们的源和目标,并在循环的每次传递中递增它们,这样我们就可以保存乘法。对每个涉及的指针执行此操作还有一个优点,即不需要变量i,这样可以保存涉及它的所有操作,只需要计算结束指针。检查不平等通常比小于&#34;小于&#34;作仪

//first post creation for @user
def setup
    @user = users(:michael)
    # This code is not idiomatically correct.
    @micropost = @user.microposts.build(content: "Lorem ipsum")
end

//second post creation in test for @user
test "associated microposts should be destroyed" do
    @user.save
    @user.microposts.create!(content: "Lorem ipsum")
    assert_difference 'Micropost.count', -1 do
    @user.destroy
end

虽然如果一些优化器能够从OP的原始代码中获得这样的代码,我不会感到惊讶。

相关问题