我想在C++中创建一个返回连续2D数组的函数。
使用以下命令创建阵列没有问题:
int (*v)[cols] = new (int[rows][cols]);
字符串
但是,我不确定如何将此数组作为函数的一般类型返回。函数是:
NOT_SURE_WHAT_TYPE create_array(int rows, int cols)
{
int (*v)[cols] = new (int[rows][cols]);
return v;
}
型
我尝试了double*[]和double**,但都不起作用。我不想使用double*,因为我想从外部访问这个2D数组。
相关问题:How do I declare a 2d array in C++ using new?
7条答案
按热度按时间ijnw1ujt1#
如果你想创建一个数据连续的数组,而不想创建一个一维数组(即你想使用
[][]
语法),那么下面应该可以工作。它创建一个指针数组,每个指针指向内存池中的一个位置。字符串
请注意,只进行了2次分配。这不仅因为分配的数量更少而更有效,而且如果内存分配失败,我们现在有更好的机会回滚已分配的内存,这与在非连续内存中分配2D数组的“传统”方式不同:
型
如果
new[]
在for
循环的操作过程中在某处抛出异常,则必须回滚之前发生的对new[]
的所有成功调用--这需要更多的代码并增加了复杂性。请注意如何在连续版本中释放内存--在连续分配时,只对
delete[]
进行两次调用,而不是对每行调用delete[]
。此外,由于数据位于连续内存中,因此假设数据位于连续内存中的算法,函数等,就像一维数组一样,现在可以通过指定M*N矩阵的开始和结束范围来使用:
[&array[0][0], &array[M-1][N])
个举例来说,您可以:
std::sort(&myArray[0][0], &myArray[M-1][N]);
个将按升序对整个矩阵进行排序,从索引
[0][0]
开始,直到最后一个索引[M-1][N-1]
。你可以通过使它成为一个真正的类来改进设计,而不是将分配/释放作为两个单独的函数。
编辑:正如注解中所说,这个类并不像RAII。我把它留给读者作为练习。上面的代码中缺少的一件事是在创建这样一个数组时检查ncol和nCols是否> 0。
编辑二:添加了一个
try-catch
,以确保在尝试分配内存时抛出std::bad_alloc
异常时,正确回滚内存分配。编辑:对于一个类似于上面的三维数组代码示例,请参阅此答案。其中包括在分配失败时回滚分配的代码。
编辑:添加了基本的RAII类:
型
jq6vz3qz2#
由于你使用的是C++而不是C,我建议你使用一个vector,而不是乱用new/delete。
你可以像这样定义一个连续的内存块:
字符串
现在你可以用类似2d数组的方式访问这个向量,公式是i*n + j,i是行索引,j是列索引,n是行的长度:
型
这和用array[i][j]访问一个二维数组是一样的。但是现在你有了一个连续的内存块的优势,你不需要担心new/delete,你可以很容易地用函数共享和返回这个向量对象。
hpxqektj3#
除非在编译时知道两个维度的大小,否则您没有太多的选择:分配一个
rows*cols
的数组,并使用整数乘法和加法来滚动您自己的2D索引。将其 Package 在一个类中可以生成一个漂亮的语法,用于使用方括号操作符访问数组元素。由于您的数组是2D的,您将需要使用代理(也称为“surrogate”)对象进行第一级数据访问。下面是一个使用
std::vector<T>
在动态内存中维护连续内存区域的小示例代码:字符串
您现在可以将
Array2D<int>
当作内建C++数组来使用:型
Running demo on ideone的一个。
wdebmtf24#
处理原始内存资源通常是令人讨厌的。最好的办法是一个简单的 Package 器:
字符串
私有继承让你可以从vector中获取所有的好处,只需要添加你的2D构造函数。Resslogy管理是免费的,因为vector ctor/dtor会发挥它们的魔力。显然,i+h*j可以改变为你想要的任何存储顺序。
vector< vector< int >>是2D的,但在内存中不会连续。
你的功能变成:
型
编辑:
您还可以使用usign子句检索其他向量接口部分,如开始/结束或大小,以使私有继承成员函数再次公开。
yv5phkfx5#
在我看来,没有一种在标准C++中定义2D动态数组的方法是完全令人满意的。
你最终不得不滚动你自己的解决方案。幸运的是,在Boost中已经有了一个解决方案。boost::multi_array:
字符串
Live demo的一个。
jogvjijk6#
PaulMcKenzie提供的“基本RAll”类是一个很好的解决方案。在我使用它的过程中,我确实发现了一个内存泄漏,在下面显示的版本中得到了修复。
内存泄漏是由于
Array2D& operator=(Array2D&& rhs) noexcept
的问题。需要删除
rhs.m_dataPtr = nullPtr
语句,以允许rhs析构函数删除从lhs交换的原始数据(池和指针)。下面是PaulMcKenzie提供的“基本RAll”类的更正代码
字符串
nzk0hqpo7#
我认为你应该写一个简单的类来 Package 一个一维数组。然后你可以用operator()重载来实现一个二维数组来获取值,并解构func来释放内存。代码如下:
字符串