我如何声明一个2d数组使用新?
比如,对于一个“普通”数组,我将:
int* ary = new int[Size]
but
int** ary = new int[sizeY][sizeX]
A)不工作/编译b)没有完成什么:
int ary[sizeY][sizeX]
所做的事。
我如何声明一个2d数组使用新?
比如,对于一个“普通”数组,我将:
int* ary = new int[Size]
but
int** ary = new int[sizeY][sizeX]
A)不工作/编译b)没有完成什么:
int ary[sizeY][sizeX]
所做的事。
当前回答
从静态数组的例子中,我假设你想要一个矩形数组,而不是锯齿形数组。你可以使用以下方法:
int *ary = new int[sizeX * sizeY];
然后你可以像这样访问元素:
ary[y*sizeX + x]
不要忘记在ary上使用delete[]。
其他回答
这个问题一直困扰着我——这是一个很常见的问题,应该已经有了一个好的解决方案,比向量的向量或滚动你自己的数组索引更好的解决方案。
当c++中应该存在一些东西,但却不存在时,第一个地方是boost.org。在那里我找到了Boost多维数组库,multi_array。它甚至包括一个multi_array_ref类,可用于包装您自己的一维数组缓冲区。
int** ary = new int[sizeY][sizeX]
应该是:
int **ary = new int*[sizeY];
for(int i = 0; i < sizeY; ++i) {
ary[i] = new int[sizeX];
}
然后清理是:
for(int i = 0; i < sizeY; ++i) {
delete [] ary[i];
}
delete [] ary;
编辑:正如Dietrich Epp在评论中指出的那样,这并不是一个轻量级的解决方案。另一种方法是使用一个大内存块:
int *ary = new int[sizeX*sizeY];
// ary[i][j] is then rewritten as
ary[i*sizeY+j]
如果只在本地或类中使用数组,则可以使用lambda表达式创建类数组对象。
int main(int argc, char **argv) {
srand(time(0));
int w = rand() % 20 + 10;
int h = rand() % 20 + 10;
{
// Here. Only one line and no memory leak.
auto arr = [=, p = std::make_unique<int[]>(w * h)](int i, int j) -> int & { return *&p[i * w + j]; };
arr(1, 0) = 6;
std::cout << arr(1, 0) << '\n';
}
}
该对象与int[][]不兼容,要将其作为参数传递,需要模板。但是当你访问一个元素时,它可以让你摆脱正确获取[i * w + j]的麻烦。
你也可以使用一个裸std::unique_ptr<int[]>和一个在lambda中实现的getter。但你可能会犯错误,引用不明确。
这个答案的目的不是添加其他答案没有涵盖的新内容,而是扩展@Kevin Loney的答案。
你可以使用轻量级声明:
int *ary = new int[SizeX*SizeY]
访问语法将是:
ary[i*SizeY+j] // ary[i][j]
但这对大多数人来说都很麻烦,可能会导致混乱。所以,你可以这样定义宏:
#define ary(i, j) ary[(i)*SizeY + (j)]
现在可以使用非常相似的语法ary(i, j) //表示ary[i][j]。 这具有简单美观的优点,同时,使用表达式代替索引也更简单,不那么令人困惑。
要访问,比如说,ary[2+5][3+8],你可以写ary(2+ 5,3 +8),而不是看起来复杂的ary[(2+5)*SizeY +(3+8)],也就是说,它节省了括号,有助于可读性。
警告:
尽管语法非常相似,但并不相同。 如果将数组传递给其他函数,则必须以相同的名称传递SizeY(或者声明为全局变量)。
或者,如果你需要在多个函数中使用数组,那么你可以在宏定义中添加SizeY作为另一个参数,如下所示:
#define ary(i, j, SizeY) ary[(i)*(SizeY)+(j)]
你懂的。当然,这会变得太长而没有用处,但它仍然可以防止+和*的混淆。
当然不推荐这样做,大多数有经验的用户会谴责这是一种糟糕的做法,但我还是忍不住要分享它,因为它很优雅。
编辑: 如果你想要一个适用于任意数量数组的可移植解决方案,你可以使用以下语法:
#define access(ar, i, j, SizeY) ar[(i)*(SizeY)+(j)]
然后你可以使用访问语法将任意大小的数组传递给调用:
access(ary, i, j, SizeY) // ary[i][j]
附注:我已经测试了这些,在g++14和g++11编译器上可以使用相同的语法(作为左值和右值)。
动态声明2D数组:
#include<iostream>
using namespace std;
int main()
{
int x = 3, y = 3;
int **ptr = new int *[x];
for(int i = 0; i<y; i++)
{
ptr[i] = new int[y];
}
srand(time(0));
for(int j = 0; j<x; j++)
{
for(int k = 0; k<y; k++)
{
int a = rand()%10;
ptr[j][k] = a;
cout<<ptr[j][k]<<" ";
}
cout<<endl;
}
}
现在,在上面的代码中,我们获取了一个双指针,并为它分配了一个动态内存,并给出了列的值。这里分配的内存仅用于列,现在对于行,我们只需要一个for循环,并为每一行分配一个动态内存。现在我们可以像使用2D数组一样使用指针。在上面的例子中,我们将随机数分配给我们的2D数组(指针)。这都是关于二维数组的DMA。