我正在使用一个库,它将图像作为一个大的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;
答案 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的原始代码中获得这样的代码,我不会感到惊讶。