实验,试图做一个小技巧:
void int_array_2d_show_impl(int** array, std::size_t rows, std::size_t cols)
{
for (std::size_t row = 0; row < rows; ++row)
for(std::size_t col = 0; col < cols; ++col)
std::clog << array[row][col]
<< (col == cols-1 ? '\n' : ' ');
}
template<std::size_t Rows, std::size_t Cols>
void int_array_2d_show_ref(int (&array)[Rows][Cols])
{
int_array_2d_show_impl((int**)array,Rows,Cols);
}
但它不起作用。静态分析器说它static_cast不允许转换int(*)[N]为int**. 当然,Sish cast 可以工作,但会破坏代码,并且int_array_2d_show_impl什么也不显示。为什么会这样?什么是UB?它们在内存中的存储方式不同吗?这样的代码不会输出任何东西,但它在没有编译时间和运行时间错误的情况下执行。至少垃圾应该已经被取出来了......
Post Scriptum:结果是这样的:
void int_array_2d_show_impl(int* array, std::size_t rows, std::size_t cols)
{
for (std::size_t row = 0; row < rows; ++row)
for(std::size_t col = 0; col < cols; ++col)
std::clog << array[row*cols+col]
<< (col == cols-1 ? '\n' : ' ');
}
template<std::size_t Rows, std::size_t Cols>
void int_array_2d_show_ref(int (&array)[Rows][Cols])
{
int_array_2d_show_impl(*array,Rows,Cols);
}
因为
int[Rows][Cols]和int**是根本不同的类型,在内存中存储的方式不同。在第一种情况下,这是一个连续的内存区域,
a[3][2]编译器自己在其中计算类型表达式,基于类型int[Rows][Cols]是指向int[Cols](!) 的指针,而不是指向int*.在
int**我们有一个指针数组,每个指针都指向某个int's 数组。这是内存布局的粗略轮廓:
再一次 - 最重要的是 -
int[Rows][Col]你不是在处理指向指针的指针int,而是处理指向的指针int[Cols]。这些是完全不同的类型!