Mảng là tập hợp các phần tử cùng kiểu, nằm liên tiếp nhau trong bộ nhớ ảo. Bộ nhớ cấp phát cho một mảng luôn là một dài ô nhớ liên tục từ phần từ đầu tiên tới phần tử cuối cùng trong mảng, dù là 1 chiều hai chiều hay n-chiều.

Với cấp phát động: Ta phải hiểu theo đúng bản chất của nó, cấp phát động cho con trỏ cấp 2, khác với cấp phát tĩnh cho mảng 2 chiều. Phân tích một chút:
- Mảng hai chiều p[Rows][Cols], hiểu theo cách trìu tượng, nó có thể biểu diễn một ma trận với Rows hàng và Cols cột.
- p[Rows][Cols], có thể hiểu nó giống như là một mảng một chiều mà mỗi phần tử của nó là một mảng một chiều khác.

VD: Sau đây là 2 cách biểu diễn 1 mảng 2 chiều bản chất giống hêt nhau, nhưng thể hiện theo 2 cách hiểu khác nhau. (Cấp phát tĩnh)

PHP Code:
int arr[5][10]; //Mảng hai chiều arr[5][10] 
Mảng được cấp phát như sau:
Code:
------------------------------------
[0,0] [0,1] [0,2].....[4,8] [4,9]
------------------------------------
Với [0,1] là ô nhớ chứa arr[0][1]; kiểu int 4 bytes, vậy tổng kích thước dải nhớ là 5*10*4= 200 bytes

PHP Code:
typedef int intARR[10]; intARR p[5]; // Mảng một chiều p[5] với kiểu dữ liệu intARR[10]; 
Code:
-------------------
[0] [1] [2] [3] [4]
-------------------
Với [0] là ô nhớ chứa intARR[0]; kiểu dữ liệu intARR[10] kích thước 10*4= 40 bytes đủ để chứa một mảng int 10 phần tử. Vậy tổng kích thước dải nhớ là 5*40= 200 bytes

- Tóm lại cách cấp phát ô nhớ không khác gì nhau. Các ô nhớ vẫn được cấp phát tĩnh và là một dải liên tiếp nhau. VẬY CẤP PHÁT CHO CON TRỎ CẤP 2 THÌ SAO.

Nhiều bạn nghĩ rằng con trỏ cấp 2 và mảng 2 chiều là giống nhau, thực tế thì nó có thể sử dụng như nhau để biểu diễn một ma trận MxN, nhưng thực tế nó không hoàn toàn giống nhau. Để dễ hiểu, các bạn có thể nghĩ theo hướng thứ 2, tất cả là mảng 1 chiều ^^

- Vậy nó khác cấp phát tĩnh thế nào

Nhìn lại đoạn code này:

[PHP]
PHP Code:
typedef int intARR[10]; intARR p[5]; // Mảng một chiều p[5] với kiểu dữ liệu intARR[10]; 
Mảng p chứa 5 phần tử, nếu hiểu theo tiêu chí con trỏ, mỗi phần từ của mảng p là một địa chỉ trỏ đến một mảng gồm 10 phần tử int.

- Nếu cấp phát động

PHP Code:
int **p=new int*[5]; 
Sẽ cấp phát một dải nhớ là 5*sizeof((int*)), ở win32 thì (int*) có giá trị là 4. Vậy nó sẽ cấp phát một dải nhớ liên tục có độ lớn là 4*5 = 20bytes cho con trỏ p.

Cấp phát tĩnh: p[1], p[2] khong nằm cạnh nhau, chính xác thì p[2]-p[1] = đúng kích thước của mảng int[10]; còn trong cấp phát cho con trỏ 2 chiều thì p[2] nằm tiếp ngay sau p[1] trong dải ô nhớ.

Code:
------------------------
p[0] p[1] p[2] p[3] p[4]
------------------------

Vậy thực tế p là một mảng 1 chiều, mà các phần tử có kiểu là (int*). và mảng đó là một dải ô nhớ liên tục. Nhưng đây là mảng con trỏ, vậy nó chỉ chứa được con trỏ mà thôi. Vậy muốn nó thành mảng 2 chiều thì làm thế nào.

- Ta sẽ cấp phát cho mỗi phần tử của mảng p một dải nhớ int[10] để chứa mảng một chiều. Nó khác cấp phát tĩnh ở chỗ, các mảng int[10] này nằm rải rác, không nhất thiết phải liên tục nhau trong bộ nhớ.

PHP Code:
    for(int i=0i<5i++)
        
p[i]=new int[10]; 
Điều này dẫn tới việc khi giải phóng bộ nhớ cho con trỏ cấp 2, ta phải giải phóng các dải nhớ cho từng con trỏ trước, sau đó giải phóng mảng con trỏ sau.

VD:
PHP Code:
    for(int i=0i<5i++)
        
delete[] p[i];
    
delete[] p
Sau đây là ví dụ hoàn chỉnh về cấp phát và giải phóng bộ nhớ cho con trỏ cấp 2, để sử dụng như một mảng 2 chiều RxC

PHP Code:
/*
TUTORIAL BY: ANHVNSE02067 - nh0ck0n10b
*/

#include <iostream>
using namespace std; #include <iomanip>
#define R 5 //5 rows
#define C 6 //6 col
int main()
{    
    
int **p;
    
/* Allocate memory */
    
p=new int*[R];
    for(
int i=0i<Ri++)
        
p[i]=new int[C];

    
/* Doing something ^^ */
    
for(int i=0i<Ri++)
        for(
int j=0j<Cj++)
            
p[i][j]=(i+1)*(j+1);

    
cout<<"Sample two-dimensions array: "<<endl<<endl;
    for(
int i=0i<Ri++)
    {
        for(
int j=0j<Cj++)
            
cout<<setw(4)<<p[i][j];
        
cout<<endl<<endl;
    }

    
/*De-allocate memory*/
    
for(int i=0i<Ri++)
        
delete[] p[i];
    
delete[] p;
    
cout<<endl;
    
system("pause");