C++ 2D动态数组

3
我正在尝试在构造函数初始化中动态分配一个2D数组到指针。
FooBar::FooBar()
    : _array( new int[10][10] )
{ }
int **_array;

然而这并不起作用。我了解到多维数组的分配方式略有不同。有没有人能够详细解释一下呢?

提前感谢。


1
嗨。在C++中,动态多维数组很丑陋。如果你真的在使用它们(而不是学习/作业),那就看看boost multi-array类型吧。 - Anycorn
5个回答

7

这里有些答案说2维数组是指一个指向其他数组的指针数组。这不是正确的(如果你只分配数组数据,那么指针应该存储在哪里!?)。实际上,2维数组是由其他数组组成的数组。因此,您需要更改成员的类型:

FooBar::FooBar()
    : _array( new int[10][10] )
{ }
int (*_array)[10];

这是因为new[]返回指向创建的数组第一个元素的指针。这个元素是由10个整数组成的数组,因此成员类型发生了变化。如果这个语法让你感到害怕,请使用一个模板来简化它(这个模板等同于boost::identity)。

template<typename T> struct identity { typedef T type; };

FooBar::FooBar()
    : _array( new int[10][10] )
{ }
identity<int[10]>::type *_array;

这实际上像是一个就地typedef。当然,与任何使用new[]的情况一样,它需要在析构函数中放置适当的delete[],并在对象被销毁时调用。
由于new[]分配具有在编译时已知类型的元素数组,因此您只能将第一个(最外层)维度设置为运行时值 - 所有其他维度必须具有在编译时已知的值。如果这不是您想要的,您将不得不分配指针数组,就像其他答案所说的那样。
但请注意,为避免进一步的混淆,那些不是多维数组。它们是单个指向其他单维数组的指针的单维数组。

4

C语言中的二维数组是指指向其他数组的指针数组。

假设我们有一个3x3的数组a(类型为int**):

a[0] (a[0] is of type int*) = [0][1][2]
a[1] (a[1] is of type int*) = [0][1][2]
a[2] (a[2] is of type int*) = [0][1][2]

这意味着需要进行两次分配,一次是针对指针数组(int**)的,其余内容是为了每个该数组元素分配空间。

第一步,分配指针数组:

int** a = new int*[10];

第二遍循环,为a的每个元素分配一个新数组:

for(int i=0; i<10; ++i)
    a[i] = new int[10];

这将在C++中给你一个“二维”数组。
正如你所看到的,这在更高维度上可能会非常麻烦,因此另一个技巧是分配10 * 10个元素并将数组用作2D(也称为“投影”):
const int ARRAY_WIDTH = 10;
const int ARRAY_HEIGHT = 10;
int* a = new int[ARRAY_WIDTH * ARRAY_HEIGHT];

    // To access a[5][2] you would use: 
a[5 + (2 * ARRAY_WIDTH)] = 0;

1
在C/C++中,-1 - 2D数组与指向数组的指针数组不同,也没有指针类型。 - Pavel Minaev
-1 LiraNuna的回答是错误的。在C/C++中,2D(或n维)数组是由编译器展开的。一个维度为[n][m]的2D数组实际上是一个维度为[nm]的线性数组,而[i][j]的访问实际上是[im + j]的访问。 - KomodoDave

3
int **array  = new int *[10];

for(int i= 0; i< 10;i++)
{
    array[i] = new int[10];
}

0
如果您不太关心性能,可以使用以下内容:
//vec2d.h
#include<vector>

template<class T>
void init2DVect(std::vector< std::vector<T> >& _T, size_t sx, size_t sy)
{
  _T.resize( sx );
  for(size_t i =0; i < sx; ++i)
  {
    std::vector<T> ins_v(sy);
    _T[i] = ins_v;
  }
}

使用案例示例:

//file: vec2d_test.cpp
#include "vec2D.h"

#include<cassert>

int main()
{
  std::vector< std::vector<int> > vi;
  size_t sx = 5;
  size_t sy = 7;
  init2DVect(vi, sx, sy);

  for(size_t i = 0; i < sx; ++i)
  {
    for(size_t j = 0; j < sy; ++j)
    {
      vi.at(i).at(j) = i*j;
    }
  }

  for(size_t i = 0; i < sx; ++i)
  {
    for(size_t j = 0; j < sy; ++j)
    {
      assert( vi.at(i).at(j) == i*j );
      assert( vi[i][j] == i*j );
    }
  }   

  return 0;
}

这种方法的优点是您不必担心内存问题,并且可以使用vector :: at()函数来抛出异常,如果超出范围... 这对于C ++作业很有用,但std :: vector的向量肯定不是最快的方法。

否则,TNT库可以解决问题。


0

如果你使用new操作符,你需要为第二维的每个元素单独分配内存空间。

int **Array;
Array = new int*[10];
for (int i = 0; i < 10; i++) {
    Array[i] = new int[10];
}

哎呀,有人比我先到了这里。 - Sei Satzparad

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接