问题:如何用new来创建一个“R行C列的A类型的二维数组”呢?(注意,下文中的有些“数组”严格意义上不能叫数组……)
方法1:指针的指针
分别用new创建数组的每一“行”即可。
int R = 2;
int C = 3;
auto ptr_2d = new A*[R]; //先new一个A*类型的“数组”
for (int i = 0; i < R; i++) {
ptr_2d[i] = new A[C]; //每个int*再指向一个A类型的“数组”
}
cout << "Type of ptr_2d: " << typeid(ptr_2d).name() << endl; //输出PP1A
cout << "Type of ptr_2d[0]: " << typeid(ptr_2d[0]).name() << endl; //输出P1A
这样的输出是(为了清晰,在A类型的构造函数和析构函数中都加上了输出语句):
Constructing A...
Constructing A...
Constructing A...
Constructing A...
Constructing A...
Constructing A...
Type of ptr_2d: PP1A
Type of ptr_2d[0]: P1A
前六行说明我们确实成功创建了2*3=6个A类型对象。ptr_2d的类型是PP1A,即“A类型的指针的指针”,而ptr_2d[0]的类型是P1A,即“A类型的指针”。
前文代码中可以发现,一个int *类型变量的typeid是Pi,而这里的ptr_2d[0]的typeid为何不是PA而是P1A呢?其实,这个1指的是是"A"这个类名的长度,如果把A改名叫Apple,那么这里输出的就应该是P5Apple了。
这种方法是通用的,无论R和C是常量还是普通的变量都可以用。即使“二维数组”的每一“行”长度不一样,也可以用这种方法定义。
这种方法定义的二维数组如何delete呢?记得new和delete要配对,既然我们写循环一行行new,自然也要写循环一行行delete。最后还要把一开始new的“int *”类型数组“ptr_2d”也delete掉。
for (int i = 0; i < R; i++)
delete[] ptr_2d[i];
delete[] ptr_2d;
输出:
Deleting A...
Deleting A...
Deleting A...
Deleting A...
Deleting A...
Deleting A...
成功啦!
但是要注意,这种方法定义的二维数组的每一“行”,在内存中不是连续的!实验:
int R = 2;
int C = 3;
auto ptr_2d = new A*[R];
for (int i = 0; i < R; i++) {
ptr_2d[i] = new A[C];
}
auto last_ptr = &(ptr_2d[0][0]);
for (int i = 0; i < 2; i++)
for (int j = 0; j < 3; j++) {
if ((i || j) && last_ptr + 1 != &(ptr_2d[i][j])) {
cout << "Incontiguous memory between ptr_2d[" << i << "][" << j
<< "] (" << &(ptr_2d[i][j]) << ") and last_ptr ("
<< last_ptr << ")" << endl;
}
last_ptr = &(ptr_2d[i][j]);
}
这样会输出Incontiguous memory between ptr_2d[1][0] (0x7fdb36c05858) and last_ptr (0x7fdb36c05840)
,说明ptr_2d[1][0]
和ptr_2d[0][2]
的地址之间的差别不是一个A类型对象的大小。
方法2:数组的指针
如果定义的二维数组只有第一位是普通变量、第二维是常量,则可以直接把每一行定义成定长的数组,写起来比较简单。如果要用这种方法定义更多维的数组,仍然只能有第一维可变,其余维度长度必须是常量。
int R = 2;
const int C = 3; //如果这里是int C = 3就不行了。
auto ptr_2d = new A[R][C]; //当然,也可以是new A[R][3],3也是常量
cout << "Type of ptr_2d: " << typeid(ptr_2d).name() << endl;
cout << "Type of ptr_2d[0]: " << typeid(ptr_2d[0]).name() << endl;
//do something...
delete[] ptr_2d;
输出:
Constructing A...
Constructing A...
Constructing A...
Constructing A...
Constructing A...
Constructing A...
Type of ptr_2d: PA3_1A
Type of ptr_2d[0]: A3_1A
Deleting A...
Deleting A...
Deleting A...
Deleting A...
Deleting A...
Deleting A...
注意这次ptr_2d的类型变成了PA3_1A,表示它是{{长度为3的}{A类型的}数组}的指针}。(太过拗口,手动断句。)