【问题标题】:C++ 2D Dynamic ArrayC++ 2D 动态数组
【发布时间】:2011-01-18 15:45:32
【问题描述】:

我正在尝试将二维数组动态分配给构造函数初始化中的指针。

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

但是这不起作用。我知道多维数组的分配方式有所不同。有没有人能详细解释一下?

提前致谢。

【问题讨论】:

  • 嗨。 C++ 中的动态多维数组很难看。如果您实际使用它们(而不是学习/作业),请查看 boost 多数组类型。

标签: c++ arrays memory dynamic


【解决方案1】:

如果您不太关心性能,可以使用以下方法:

//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 library 可以解决问题。

【讨论】:

    【解决方案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[] 分配的元素数组具有在编译时已知的类型,因此您只能将第一个(最外层)维度设置为运行时值 - 所有其他维度必须具有在编译时已知的值。如果这不是您想要的,您将不得不分配一个指针数组,就像其他一些答案所说的那样。

    但请注意,为避免进一步混淆,这些不是多维数组。它们是指针的一维数组,恰好指向其他一维数组。

    【讨论】:

      【解决方案3】:

      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 LiraNuna 的这个答案不正确。 C/C++ 中的二维(或 n 维)数组被编译器展平。一个维度为 [n][m] 的二维数组实际上是一个维度为 [nm] 的线性数组,而对 [i][j] 的访问实际上是对 [im + j 的访问].
      【解决方案4】:

      如果使用new,则需要单独分配第二维的每一块。

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

      【讨论】:

      • 糟糕,有人先到了。
      【解决方案5】:
      int **array  = new int *[10];
      
      for(int i= 0; i< 10;i++)
      {
          array[i] = new int[10];
      }
      

      【讨论】:

        猜你喜欢
        • 2012-11-23
        • 1970-01-01
        • 2021-10-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-06-26
        • 1970-01-01
        • 2013-02-12
        相关资源
        最近更新 更多