代码之家  ›  专栏  ›  技术社区  ›  Killzone Kid

在堆上创建多维数组

  •  2
  • Killzone Kid  · 技术社区  · 7 年前

    在一些实验之后,我提出了在堆上创建多维数组的四种方法(1和2有点相同,除了我想要引用的1的结果之外):

    #include <memory>
    #include <iostream>
    
    template <typename T>
    void printArr(T const &arr)
    {
        std::cout << typeid(T).name() << "\t";
        for (int x = 0; x < 2; ++x)
            for (int y = 0; y < 2; ++y)
                for (int z = 0; z < 2; ++z)
                    std::cout << arr[x][y][z] << " ";
        std::cout << std::endl;
    }
    
    
    int main()
    {
        int(&arr)[2][2][2] = reinterpret_cast<int(&)[2][2][2]>(*new int[2][2][2]{ { { 1,2 },{ 3,4 } }, { { 5,6 },{ 7,8 } } });
        printArr(arr);
        delete[] &arr;
    
        int(*arr2)[2][2] = new int[2][2][2]{ { { 1,2 },{ 3,4 } },{ { 5,6 },{ 7,8 } } };
        printArr(arr2);
        delete[] arr2;
    
        std::unique_ptr<int[][2][2]> arr3(new int[2][2][2]{ { { 1,2 },{ 3,4 } },{ { 5,6 },{ 7,8 } } });
        printArr(arr3);
    
        std::unique_ptr<int[][2][2]> arr4 = std::make_unique<int[][2][2]>(2);
        printArr(arr4);
    
        return 0;
    }
    

    在各种在线编译器上测试过,没有问题,那么我想知道它们是否也是有效的方法呢?

    这是演示 https://ideone.com/UWXOoW 输出:

    int [2][2][2]   1 2 3 4 5 6 7 8
    int (*)[2][2]   1 2 3 4 5 6 7 8
    class std::unique_ptr<int [0][2][2],struct std::default_delete<int [0][2][2]> > 1 2 3 4 5 6 7 8
    class std::unique_ptr<int [0][2][2],struct std::default_delete<int [0][2][2]> > 0 0 0 0 0 0 0 0
    
    1 回复  |  直到 7 年前
        1
  •  1
  •   Michael Kenzel    7 年前

    我认为您的第一个示例是未定义的行为,或者至少在您试图通过引用实际访问数组时会导致未定义的行为 arr .

    new int[2][2][2] 创建两个数组 int[2][2] . 它返回指向该数组第一个元素的指针( [expr.new] §1 )但是,指向数组第一个元素的指针和指向数组本身的指针不是 pointer interconvertible . 我不确定对于哲学问题是否有一个明确的答案:“去引用一个无效指针的行为本身是否已经构成了未定义的行为?”。但至少访问从您的reinterpret-cast获得的引用应该绝对违反 strict aliasing rule . 另外三个应该是好的。

    编辑:

    由于仍有一些困惑,下面是对我的论点的更详细的解释:

    new int[2][2][2]
    

    创建两个数组 INT〔2〕〔2〕 并返回指向该数组第一个元素的指针,即指向第一个元素的指针 INT〔2〕〔2〕 子对象 在内部 这个数组和 不是整个数组对象本身 .

    如果你想得到 int(*)[2][2][2] new 你可以,例如

    new int[1][2][2][2]