如何使用'new'运算符声明二维数组?我的书说:
int (*p)[4];
p=new[3][4];
但对我来说没有意义。 p是一个指向4个整数数组的指针,那怎么能指向一个二维数组?
答案 0 :(得分:8)
似乎你需要指向指针的指针。编辑:嗯,更确切地说,以下示例创建指向数组的指针数组。
首先:
int **p = new int*[NUM];
这里你已经创建了一系列指针。现在,您需要为每个数组创建另一个数组。你可以这样做:
for(int i = 0; i < NUM; i++)
{
p[i] = new int[ANOTHER_NUM];
}
对于释放你做的相似,但反过来:
for(int i = 0; i < NUM; i++)
{
delete[] p[i];
}
最后:
delete[] p;
现在你可以使用它了。这样你就可以创建N维数组,只需添加更多'*'。如果您有任何其他特殊问题,请在评论中提问。
但是,一般来说,有关详细信息,我建议您首先尝试使用“C ++中的2D数组”或“2D数组C ++的动态分配”等问题。即this query
答案 1 :(得分:4)
其他答案包括为您的行指定一个指针数组,每行指向一个int
数组。另一种选择是简单地分配足够大的1-D阵列来容纳所有2-D阵列的元素:
int* p = new int [3 * 4];
然后,您使用p[r][c]
而不是p[r * kNumCols + c]
语法。在此示例中,kNumCols = 4
。这通常是在LAPACK式数字运算中完成的,因为它在内存中保持连续,并且您不需要分配这么多内存块。
注意:这通常不比实际中的替代方案慢,因为行偏移计算通过公共子表达式优化移出循环。此外,许多优化器都知道要寻找这种模式。此外,通过将数据保持在单个内存块中,数据更有可能保留在缓存中。
在C ++中,您可以使用帮助器模板类实现p[][]
表示法:
template<class T>
class Array2DPtrRow
{public:
Row(T* row_): row(row_) {}
operator T*() { return row; }
T& operator [](size_t c) { return row[c]; }
private:
T* row;
};
template<class T, size_t NC>
class Array2DPtr
{public:
Array2DPtr(T* buf_): buf(buf_) {}
operator T*() { return buf; }
Array2DPtrRow<T> operator [](size_t r)
{ return Array2DPtrRow<T>(buf + NC * r); }
private:
T* buf;
};
这可以优化到与上面相同的代码,但允许您使用[][]
表示法,要求您在编译时知道数组维度。用法示例:
Array2DPtr<int, 4> p(new int[3 * 4]);
p[1][2];
这可以转换为使NC成为类成员而不是模板参数,但最终对象不再只是一个指针:
template<class T>
class Array2DPtr
{public:
Array2DPtr(T* buf_, size_t nc_): buf(buf_), nc(nc_) {}
operator T*() { return buf; }
Array2DPtrRow<T> operator [](size_t r)
{ return Array2DPtrRow<T>(buf + nc * r); }
private:
T* buf;
size_t nc;
};
Array2DPtr<int> p(new int[3 * 4], 4);
p[1][2];
请注意,这些类都不需要复制构造函数,赋值运算符或析构函数,因为它们不会像常规指针那样获取指向内存的所有权。所以要释放内存,你仍然需要这样做:
delete[] p;
或者如果您的编译器无法弄明白:
delete[] (int*)p;
答案 2 :(得分:2)
有几种方法可以在C中声明多维数组。
您可以将p
显式声明为2D数组:
int p[3][4]; // All of p resides on the stack.
(请注意,除非您正在使用C ++并希望在堆上分配它们,否则此处不需要new
作为基本类型。)
或者你可以将它声明为指针的向量(1D数组),然后为每个向量分配内存:
int *p[3]; // The vector addresses reside on the stack.
for (int i=0; i<3; i++) {
p[i] = malloc(4 * sizeof(int)); // Each element resides on the heap.
}
// You can now access p as p[j][k] as if it were a 2D array.
for (int i=0; i<3; i++) {
free p[i];
}
或者,如果您不知道任何一个维度,则可以动态分配整个2D数组:
#define WIDTH 3
#define HEIGHT 4
int **p; // Base address resides on the stack.
p = malloc(WIDTH * sizeof(int *)); // Pointers to vectors reside on the heap.
for (int i=0; i<WIDTH; i++) {
p[i] = malloc(HEIGHT * sizeof(int)); // Data values reside on the heap.
}
// You can now access p as p[j][k] as if it were a 2D array.
// Release the memory that was allocated to each vector.
for (int i=0; i<WIDTH; i++) {
free(p[i]);
}
// Release the memory that was allocated to the initial pointer.
free(p);
答案 3 :(得分:2)
要真正回答这个问题:
请记住,数组等同于指向数组第一个元素的指针,例如,您可以编写:
char str[14] = "Hello, world!";
char *ptr = str;
这也适用于二维数组。
int (*p)[4];
声明指向二维数组的第一个元素的指针。然后p
可以指向任何二维数组,只要它的第二维是4,所以例如你可以写
int arr[3][4];
int (*p)[4] = arr;
当然你也可以动态分配内存:
int (*p)[4] = new int[3][4];
同样,第二个维度必须为4,但您可以改变第一个维度。
答案 4 :(得分:1)
你需要这样的东西
int **array_ptr; //two * are needed because it is a pointer to a pointer
array_ptr=new int*[firstnumber]; //creates a new array of pointers to int objects
for(int i=0; i<firstnumber; ++i)
array_ptr[i]=new int[secondnumber];