C++如何简单地在堆上创建多维数组?

2022-08-08 22:44:16 +08:00
 wisefree

如果直接在栈上创建维数很高的多维数组,会有爆栈的风险。

在 stackflow 上搜索了一个回答,感觉很新颖,示例如下。请问下大家有其他方法能简单地在堆上创造多维数组吗?

#include <memory>

struct Foo
{
    int arr[100][200][100];
};

int main()
{
    auto foo = std::make_unique<Foo>(); // allocate on the heap
    auto& arr = foo->arr;

    arr[1][2][3] = 42;

    return 0;
}

https://stackoverflow.com/questions/59082203/c-declaring-a-static-contiguous-multi-dimensional-array-on-the-heap-the-right

2438 次点击
所在节点    C++
11 条回复
codehz
2022-08-08 22:52:18 +08:00
直接用 std::array 不好吗)
wisefree
2022-08-08 22:56:59 +08:00
@codehz std::array 是在栈上
BrettD
2022-08-08 23:00:19 +08:00
codehz
2022-08-08 23:00:32 +08:00
@wisefree 你 new std::array 不就可以了?,或者用 unique_ptr 装最外层
yyt6801
2022-08-09 00:17:56 +08:00
new
darer
2022-08-09 00:22:33 +08:00
自定义类封装一维数组,重载()
ysc3839
2022-08-09 00:40:06 +08:00
用 C 的连续多维数组主要还是想用多维转成偏移量的语法糖吧,如果一定要用这个语法糖的话那只有楼主说的这种这种方法了。否则只能依赖 C++的特性,比如 std::array 容器嵌套。
cnbatch
2022-08-09 00:53:56 +08:00
我之前也有这样的需求,但需要更加灵活,大小并非编译时固定,而是类似于 C 语言的那种 VLA (正好就是曾经有望入标准库但最终被放弃的 std::dynarray ),于是仿照 std::dynarray 和 std::vector 的 API 弄了个简单的实现:
https://github.com/cnbatch/dynarray
默认在堆上分配,而非栈上分配。

我在里面提供了两种写法的版本。

写法 1 (位于 vla_nest/dynarray.hpp ):
int x = 100, y = 200;
int value = 5;
vla::dynarray<vla::dynarray<int>> vla_array(x, y, value); // 相当于 int[x][y],全部初始化为 5

写法 2 (位于 vla_cleanlily/dynarray.hpp ):
int x = 100, y = 200;
int value = 5;
vla::dynarray<int, 2> vla_array(x, y, value); // 意思同上例,其中<int, 2>的意思是,创建 int 类型的二维数组

写法 1 看起来更“传统”一点,这是我最初的习惯。后来有人跟我说弄成写法 2 这种更加美观,我想了想觉得很对,于是就加了这个版本。

创建完成后的用法就跟普通数组无异,都是
vla_array[3][1] = 100;
vla_array[5][5] = vla_array[2][2];
yanqiyu
2022-08-09 09:04:22 +08:00
为什么不直接 auto arr = std::make_unique<int[][100][100]>(100)
yanqiyu
2022-08-09 09:06:02 +08:00
@wisefree std::array 本质上就是你的 Foo ,只是附赠更多语法糖
ColorfulBoar
2022-08-16 12:22:48 +08:00
在不在堆上其实不是个问题……总的来说建议不要用“多维数组”,然后把它分成「一坨数据」和「访问方式」两部分,这样不管是写起来还是用起来还是做优化都比较方便(就像 graphics API 里面总是把 texture 和 view 分开一样)。
举个只用标准库的朴素例子:

(没有 C++23 自己去毛一个 https://github.com/kokkos/mdspan

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/871538

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX