在堆上创建多维数组

Creating multidimensional array on the heap

本文关键字:数组 创建      更新时间:2023-10-16

经过一些实验,我想出了这四种在堆上创建多维数组的方法(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

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

new int[2][2][2]创建一个包含两个int[2][2]的数组。它返回指向此数组的第一个元素的指针 ([expr.new] §1)。但是,指向数组第一个元素的指针和指向数组本身的指针不是指针可相互转换的。我不确定对于哲学问题"取消引用无效指针的行为本身是否已经构成未定义的行为?"是否有明确的答案。但至少访问从reinterpret_cast获得的引用绝对应该违反严格的混叠规则。其他三个应该没问题。

编辑:

由于似乎仍然存在一些混乱,这里对我的论点进行更详细的解释:

new int[2][2][2]

创建一个包含两个int[2][2]的数组,并返回指向该数组的第一个元素的指针,即指向此数组第一个int[2][2]子对象的指针,而不是完整的数组对象本身

如果你想从new那里得到一个int(*)[2][2][2],你可以,例如,

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