在堆上创建多维数组

时间:2018-07-28 18:17:19

标签: c++ multidimensional-array c++14 heap language-lawyer

经过一些实验,我想出了在堆上创建多维数组的四种方法(除了1和2的结果我想参考之外)(1和2差不多):

#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 个答案:

答案 0 :(得分:1)

我认为您的第一个示例是未定义的行为,或者至少在您尝试通过引用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]子对象 中的指针em>不是完整的数组对象本身。

如果您想从int(*)[2][2][2]获取new,则可以这样做

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