如何用new來創建二維數組

問題:如何用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類型的}數組}的指針}。(太過拗口,手動斷句。)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章