4

如何使用“新”运算符声明二维数组?我的书是这样说的:

int (*p)[4];
p=new[3][4];

但这对我来说没有意义。p 是一个指向 4 个整数数组的指针,那么如何让它指向一个二维数组呢?

4

5 回答 5

10

看来您需要指向指针的指针。编辑:好吧,更准确地说,以下示例创建了一个指向数组的指针数组

首先做:

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++ 中的二维数组”或“二维数组 C++ 的动态分配”之类的问题,即这个查询

于 2012-04-08T12:14:07.417 回答
5

其他答案包括为您的行提供一个指针int数组,每行都有一个指向数组的指针。另一种选择是简单地分配一个足够大的一维数组来容纳所有二维数组的元素:

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;
于 2012-04-08T12:17:09.147 回答
3

要真正回答这个问题:

请记住,数组等效于指向数组第一个元素的指针,因此例如您可以编写:

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,但您可以更改第一个维度。

于 2012-04-08T21:37:08.787 回答
2

在 C 中声明多维数组有几种方法。

您可以p显式声明为二维数组:

int p[3][4];  // All of p resides on the stack.

(请注意,new这里不需要基本类型,除非您使用 C++ 并希望在堆上分配它们。)

或者您可以将其声明为指针向量(一维数组),然后为每个向量分配内存:

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];
}

或者,如果您不知道任一维度,则可以动态分配整个二维数组:

#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);
于 2012-04-08T12:10:06.837 回答
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];
于 2012-04-08T12:09:38.277 回答