我如何声明一个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]
所做的事。
当前回答
我使用这个不优雅,但快速,简单和工作系统。我不明白为什么不能工作,因为系统允许创建一个大尺寸数组和访问部分的唯一方法是不切割它的部分:
#define DIM 3
#define WORMS 50000 //gusanos
void halla_centros_V000(double CENW[][DIM])
{
CENW[i][j]=...
...
}
int main()
{
double *CENW_MEM=new double[WORMS*DIM];
double (*CENW)[DIM];
CENW=(double (*)[3]) &CENW_MEM[0];
halla_centros_V000(CENW);
delete[] CENW_MEM;
}
其他回答
在c++ 11及以上版本中,我推荐两种通用技术,一种用于编译时维度,另一种用于运行时维度。这两个答案都假设您需要统一的二维数组(而不是锯齿状数组)。
编译时维度
使用std::array的std::array,然后使用new把它放到堆上:
// the alias helps cut down on the noise:
using grid = std::array<std::array<int, sizeX>, sizeY>;
grid * ary = new grid;
同样,这仅适用于在编译时已知维度大小的情况。
运行时维度
实现只有在运行时才知道大小的二维数组的最佳方法是将其包装到一个类中。该类将分配一个1d数组,然后重载操作符[]来为第一个维度提供索引。 这是因为在c++中,2D数组是行为主的:
(摘自http://eli.thegreenplace.net/2015/memory-layout-of-multi-dimensional-arrays/)
连续的内存序列有利于提高性能,而且易于清理。下面是一个示例类,省略了很多有用的方法,但显示了基本思想:
#include <memory>
class Grid {
size_t _rows;
size_t _columns;
std::unique_ptr<int[]> data;
public:
Grid(size_t rows, size_t columns)
: _rows{rows},
_columns{columns},
data{std::make_unique<int[]>(rows * columns)} {}
size_t rows() const { return _rows; }
size_t columns() const { return _columns; }
int *operator[](size_t row) { return row * _columns + data.get(); }
int &operator()(size_t row, size_t column) {
return data[row * _columns + column];
}
}
因此,我们用std::make_unique<int[]>(行*列)项创建一个数组。我们重载操作符[],它将为我们索引行。它返回一个int *,指向该行的开头,然后可以像对列一样对该行进行解引用。注意,make_unique在c++ 14中首次发布,但如果需要,可以在c++ 11中填充它。
对于这些类型的结构,重载operator()也是很常见的:
int &operator()(size_t row, size_t column) {
return data[row * _columns + column];
}
从技术上讲,我在这里没有使用new,但是从std::unique_ptr<int[]>移动到int *并使用new/delete是很简单的。
如何分配一个连续的多维数组在GNU c++ ?有一个GNU扩展允许“标准”语法工作。
问题似乎来自操作符new[]。请确保使用operator new:
double (* in)[n][n] = new (double[m][n][n]); // GNU extension
这就是全部:你得到了一个c兼容的多维数组……
下面的例子可能会有所帮助,
int main(void)
{
double **a2d = new double*[5];
/* initializing Number of rows, in this case 5 rows) */
for (int i = 0; i < 5; i++)
{
a2d[i] = new double[3]; /* initializing Number of columns, in this case 3 columns */
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 3; j++)
{
a2d[i][j] = 1; /* Assigning value 1 to all elements */
}
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 3; j++)
{
cout << a2d[i][j] << endl; /* Printing all elements to verify all elements have been correctly assigned or not */
}
}
for (int i = 0; i < 5; i++)
delete[] a2d[i];
delete[] a2d;
return 0;
}
试着这样做:
int **ary = new int* [sizeY];
for (int i = 0; i < sizeY; i++)
ary[i] = new int[sizeX];
这个答案的目的不是添加其他答案没有涵盖的新内容,而是扩展@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编译器上可以使用相同的语法(作为左值和右值)。