【问题标题】:How to heap allocate a 2D array in C++? [duplicate]如何在 C++ 中堆分配二维数组? [复制]
【发布时间】:2017-09-26 20:02:46
【问题描述】:

我正在尝试做这样的事情:

std::string* Plane = new std::string[15][60];

但是,这段代码似乎无法编译。 有没有其他方法可以达到同样的效果? 感谢您提供任何潜在的帮助。

【问题讨论】:

  • 为什么不使用std::arraystd::vector? (例如:std::array< std::array<std::string, 15>, 60>
  • std::string* 不是二维的
  • @UnholySheep std::array 很好 - 但需要反转维度...

标签: c++ arrays heap-memory


【解决方案1】:

有三种方法可以做到这一点。

首先是将其分配为“数组数组”结构(我将您的代码转换为std::vector,因为它比处理原始指针更安全)。如果您需要每一行都有自己的长度,这是理想的选择,但会占用额外的内存:

std::vector<std::vector<std::string>> Plane(15);
for(size_t index = 0; index < 15; index++)
    Plane[index].resize(60);

for(size_t i = 0; i < 15; i++)
    for(size_t j = 0; j < 60; j++)
        Plane[i][j] = "This is a String!";

第二种是将其分配为扁平结构,以降低灵活性为代价显着提高性能:

std::vector<std::string> Plane(15 * 60);

for(size_t i = 0; i < 15; i++)
    for(size_t j = 0; j < 60; j++)
        Plane[i* 60 + j] = "This is a String!";

第三个,由于它的可扩展性,我认为这是迄今为止最好的选择,它是滚动一个 Matrix 类,它为您抽象出这些细节,从而减少您在编码中出错的可能性:

template<typename T>
class Matrix {
    std::vector<T> _data;
    size_t rows, columns;
public:
    Matrix(size_t rows, size_t columns) : rows(rows), columns(columns), _data(rows * columns) {}

    T & operator()(size_t row, size_t column) {
        return _data[row * columns + column];
    }

    T const& operator()(size_t row, size_t column) const {
        return _data[row * columns + column];
    }
};

Matrix<std::string> Plane(15, 60);
for(size_t i = 0; i < 15; i++)
    for(size_t j = 0; j < 60; j++)
        Plane(i, j) = "This is a String!";

当然,这是一个极其简化的实现;您可能想要添加一堆类似 STL 的功能,例如 rows()columns()at()begin()end() 等。

【讨论】:

  • 替代 std::vector(没有提到的开销,仍然是 STL 容器):std::array -- 可能最好与 typedef 一起使用...
  • @Aconcagua std::array 如果您不需要动态内存,这是一个不错的选择,OP 的问题暗示了这一点——如果堆栈分配是一个合适的解决方案,他们可能会写 std::string Plane[15][60]; .
【解决方案2】:

当使用new[]分配多维数组时,必须分别分配每个维度,例如:

std::string** Plane = new std::string*[15];
for(int i = 0; i < 15; ++i)
    Plane[i] = new std::string[60];

...

for(int i = 0; i < 15; ++i)
    delete[] Plane[i];
delete[] Plane;

要访问给定行/列对的字符串,您可以使用Planes[row][column] 语法。

否则,将其展平为一维数组:

std::string* Plane = new std::string[15*60];
...
delete[] Plane;

要访问给定行/列对的字符串,您可以使用Planes[(row*60)+column] 语法。

话虽如此,您应该远离使用这样的原始指针。请改用std::vectorstd::array

typedef std::vector<std::string> string_vec;
// or, in C++11 and later:
// using string_vec = std::vector<std::string>;
std::vector<string_vec> Planes(15, string_vec(60));

// C++11 and later only...
std::vector<std::array<std::string, 60>> Planes(15);

// C++11 and later only...
using Plane_60 = std::array<std::string, 60>;
std::unique_ptr<Plane_60[]> Planes(new Plane_60[15]);

// C++14 and later only..
using Plane_60 = std::array<std::string, 60>;
std::unique_ptr<Plane_60[]> Planes = std::make_unique<Plane_60[]>(15);

其中任何一个都可以让您使用Planes[row][column] 语法访问字符串,同时为您管理数组内存。

【讨论】:

  • 非常感谢您的帮助!祝你有美好的一天!
  • 为了完整起见:std::string(*planes)[60]std::string(*planes)[15][60] 也可以使用(并且可以再次使用 new std::string[15][16] 而不是循环)。当然,这(如果有的话)只有与适当的 typedef 一起使用才好……而且我还缺少new std::array&lt;std::array&lt;std::string, 60&gt;, 15&gt;() 方法(尽管有人应该提到尺寸倒置的丑陋部分——但这发生在 make_unique 上,太...)。
  • new std::string[15][60] 不是有效的语法并且无法编译,如 OP 的问题中所述。我回答的重点是完全避免使用new[](除非std::make_unique&lt;T[]&gt;() 不可用)。
猜你喜欢
  • 2015-06-23
  • 1970-01-01
  • 2021-11-30
  • 1970-01-01
  • 2015-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多