【问题标题】:A way of allocating multidimensional arrays dynamically一种动态分配多维数组的方法
【发布时间】:2011-06-30 18:48:54
【问题描述】:

敬礼..

我正在在一本书中学习多维数组的动态分配,我找到了一些方法,现在没有问题了。 但是本书的作者向我们展示了一种方法,但它不能正常工作。是这样的:

pbeans = new double [3][4];         // Allocate memory for a 3x4 array

这是错误:

error C2440: '=' : cannot convert from 'int (*)[4]' to 'int *'

我应该如何定义pbeans(如果这种编码是合法的)?

究竟是什么问题?

问候。

【问题讨论】:

  • 您可能会发现C++ Faqs(以及紧随其后的常见问题解答)有助于理解这一点。顺便说一句,这是一件好事,但通常你应该只使用容器类(例如,标准模板库)。如果您确实使用new,您通常希望将其包装在容器类中,或者至少使用智能指针。 Tenfour 的代码看起来比 Alnitak 的更复杂,因为它更适合生产环境;它通过RAII 保护您免受内存泄漏

标签: c++ pointers multidimensional-array


【解决方案1】:

这在我的FAQ on arrays:

double (*pbeans)[4];
pbeans = new double[3][4];

// ...

delete[] pbeans;

对于“C 声明器受损”,您可以使用 typedef 使其更具可读性:

typedef double row[4];

row *pbeans;
pbeans = new row[3];

// ...

delete[] pbeans;

但在 C++ 中,我们更喜欢 RAII 容器而不是原始指针:

#include <vector>
#include <array>

std::vector<std::array<double, 4> > beans(3);

请注意完全没有 delete[],这使得该解决方案异常安全。

【讨论】:

  • 我更喜欢这种方法,因为它也很清楚你的尺寸代表什么。
  • @C77:请注意,原始错误消息已经暗示了 pbeans 所需的类型:int (*)[4]。只是许多程序员不知道这种有趣的标记组合可能意味着什么。诅咒你,C 声明符语法!
  • 如果值是静态的,那么新/删除就没有新的了。如果两者都是动态的,则需要分别释放每一行,请参见此处的 p2DArray 示例:cplusplus.com/forum/articles/7459
【解决方案2】:

这是一种在堆上连续分配内存的方法:

typedef double MyGrid[3][4];

int main(int argc, char* argv[])
{
    MyGrid& x = *(reinterpret_cast<Grid*>(new double[12]));
    ...
    x[1][2] = 0.3333;
    ...
    delete[] &x;
    return 0;
}

您可以轻松地将其转化为更通用的解决方案:

template<typename T, int x, int y>
struct Array2D
{
    typedef T CArrayType[x][y];
    typedef CArrayType& RefType;
    static CArrayType& New()
    {
        return *(reinterpret_cast<CArrayType*>(new T[x * y]));
    }
    static void Delete(RefType x)
    {
        delete[] &x;
    }
};

typedef Array2D<double, 3, 4> MyGrid;// define your 2d array with 3 rows / 4 columns.

int main(int argc, char* argv[])
{
    MyGrid::RefType j = MyGrid::New();
    ...
    j[1][2] = 0.3333;
    ...
    MyGrid::Delete(j);
    return 0;
}

这个想法是只生成 1D (x*y) 中的元素,并将其转换为 2D 数组。但是由于数组类型是值类型,因此您需要处理指向数组的指针。使用引用使其几乎透明。

Boost 可能有这样的东西,但我对 boost 的了解还不足以说...

【讨论】:

  • @C77431:与 Alnitak 的回答不同,这将在内存中连续分配多维数组。这可能是也可能不是您想要的。
  • 不用投,看我的回答。
【解决方案3】:

你需要单独分配数组的每个维度:

double **pbeans = new double*[3];
for (int i = 0; i < 3; ++i) {
    pbeans[i] = new double[4];
}

【讨论】:

  • 谢谢,那是非法的,我应该把书放在回收站吗? (:
  • 好吧,你可以double pbeans[3][4],但这会在堆栈而不是堆上创建变量。
  • 实际上,您可以动态创建多维数组,而无需单独分配每个维度。看我的回答。
猜你喜欢
  • 2017-03-18
  • 2020-04-24
  • 2011-08-15
  • 2011-05-31
  • 1970-01-01
  • 1970-01-01
  • 2013-04-02
  • 1970-01-01
  • 2012-10-07
相关资源
最近更新 更多