V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
wisefree
V2EX  ›  C++

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

  •  
  •   wisefree · 60 天前 · 1583 次点击
    这是一个创建于 60 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    在 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

    11 条回复    2022-08-16 12:22:48 +08:00
    codehz
        1
    codehz  
       60 天前 via iPhone   ❤️ 1
    直接用 std::array 不好吗)
    wisefree
        2
    wisefree  
    OP
       60 天前
    @codehz std::array 是在栈上
    codehz
        4
    codehz  
       60 天前 via iPhone   ❤️ 1
    @wisefree 你 new std::array 不就可以了?,或者用 unique_ptr 装最外层
    yyt6801
        5
    yyt6801  
       60 天前 via Android
    new
    darer
        6
    darer  
       60 天前
    自定义类封装一维数组,重载()
    ysc3839
        7
    ysc3839  
       60 天前 via Android   ❤️ 1
    用 C 的连续多维数组主要还是想用多维转成偏移量的语法糖吧,如果一定要用这个语法糖的话那只有楼主说的这种这种方法了。否则只能依赖 C++的特性,比如 std::array 容器嵌套。
    cnbatch
        8
    cnbatch  
       59 天前   ❤️ 1
    我之前也有这样的需求,但需要更加灵活,大小并非编译时固定,而是类似于 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
        9
    yanqiyu  
       59 天前   ❤️ 1
    为什么不直接 auto arr = std::make_unique<int[][100][100]>(100)
    yanqiyu
        10
    yanqiyu  
       59 天前   ❤️ 1
    @wisefree std::array 本质上就是你的 Foo ,只是附赠更多语法糖
    ColorfulBoar
        11
    ColorfulBoar  
       52 天前   ❤️ 1
    在不在堆上其实不是个问题……总的来说建议不要用“多维数组”,然后把它分成「一坨数据」和「访问方式」两部分,这样不管是写起来还是用起来还是做优化都比较方便(就像 graphics API 里面总是把 texture 和 view 分开一样)。
    举个只用标准库的朴素例子:

    (没有 C++23 自己去毛一个 https://github.com/kokkos/mdspan
    关于   ·   帮助文档   ·   API   ·   FAQ   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   1645 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 44ms · UTC 16:49 · PVG 00:49 · LAX 09:49 · JFK 12:49
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.