面试题答案
一键面试#include <iostream>
// 函数声明
int (*transpose(int (*threeD)[3][4]))[3][2];
int main() {
int threeD[2][3][4] = {
{
{1, 2, 3, 4},
{5, 6, 7, 8},
{9, 10, 11, 12}
},
{
{13, 14, 15, 16},
{17, 18, 19, 20},
{21, 22, 23, 24}
}
};
int (*transposed)[3][2] = transpose(threeD);
// 输出转置后的数组
for (int k = 0; k < 4; ++k) {
for (int j = 0; j < 3; ++j) {
for (int i = 0; i < 2; ++i) {
std::cout << transposed[k][j][i] << " ";
}
std::cout << std::endl;
}
std::cout << std::endl;
}
return 0;
}
// 函数定义
int (*transpose(int (*threeD)[3][4]))[3][2] {
static int transposed[4][3][2];
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 4; ++k) {
transposed[k][j][i] = threeD[i][j][k];
}
}
}
return transposed;
}
指针类型匹配
- 参数指针类型:函数接收一个指向
int [3][4]
的指针,因为三维数组名在传递给函数时会退化为指向其首元素的指针,而threeD
的首元素类型是int [3][4]
。 - 返回指针类型:函数返回一个指向
int [3][2]
的指针,因为转置后的数组类型为int [4][3][2]
,返回的指针指向该数组的首元素,其类型为int [3][2]
。
内存管理问题
- 静态数组:这里使用静态数组
transposed
来存储转置后的结果。静态数组的生命周期与程序相同,在函数调用结束后不会被销毁,保证了返回的指针始终有效。 - 动态内存分配:如果不使用静态数组,也可以使用动态内存分配(如
new
运算符)来创建转置后的数组。但这样做需要在调用者中负责释放内存,以避免内存泄漏。例如:
int (*transpose(int (*threeD)[3][4]))[3][2] {
int (*transposed)[3][2] = new int[4][3][2];
for (int i = 0; i < 2; ++i) {
for (int j = 0; j < 3; ++j) {
for (int k = 0; k < 4; ++k) {
transposed[k][j][i] = threeD[i][j][k];
}
}
}
return transposed;
}
在调用者中使用完后需要使用delete[]
来释放内存:
int main() {
int threeD[2][3][4];
int (*transposed)[3][2] = transpose(threeD);
// 使用 transposed
delete[] transposed;
return 0;
}
使用动态内存分配需要更谨慎的内存管理,而静态数组虽然简单,但如果函数多次调用,可能会导致数据覆盖问题,需要根据具体需求选择合适的方法。