C++——多維數組動態開辟與釋放


前言

在討論多維數組動態開辟與釋放之前,先說說什么是二維數組靜態開辟與釋放。

形如這種就是靜態開辟內存,事先畫好了內存大小

#include<iostream>
using namespace std;

#define ROW 3
#define COL 4
int main()
{
    int ar[COL][ROW] = { 0 };
    return 0;
}
View Code

 

使用二級指針模擬二維數組

代碼演示

#include<iostream>
#include<assert.h>
using namespace std;

#define ROW 3
#define COL 4
int main()
{
    int **p=(int**)malloc(sizeof(int*)*ROW);
    assert(NULL != p);
    for (int i=0;i<ROW;++i)
    {
        p[i] = (int*)malloc(sizeof(int)*COL);
        assert(NULL!=p[i]);
    }
    for (int i = 0; i< ROW; ++i)
    {
        for (int j = 0; j < COL; ++j)
        {
            p[i][j] = i + j;
        }
    }
    for (int i = 0; i< ROW; ++i)
    {
        for (int j = 0; j < COL; ++j)
        {
            cout << p[i][j]<<" ";
        }
        cout << endl;
    }
    return 0;
}
View Code

這段代碼有個問題,內存泄漏。

泄露內存大小為4*3 + 4*4*3 = 60 Byte。我們知道,進程的用戶空間內存中有一段內存是程序運行時需要的(堆、棧、共享內存區),棧內存由OS動態開辟回收,我們malloc的內存時是在堆中,需要我們手動釋放,否則就會內存泄露。

free(p)這么釋放內存可以嗎?

不可以,這么僅僅是把3個int*釋放了,后面int*指向的內存泄露。

正確釋放內存,先釋放int*指向的內存,在釋放p指向的內存(即3個int*內存)

 1 #include<iostream>
 2 #include<assert.h>
 3 using namespace std;
 4 
 5 #define ROW 3
 6 #define COL 4
 7 int main()
 8 {
 9     int **p=(int**)malloc(sizeof(int*)*ROW);
10     assert(NULL != p);
11     for (int i=0;i<ROW;++i)
12     {
13         p[i] = (int*)malloc(sizeof(int)*COL);
14         assert(NULL!=p[i]);
15     }
16     for (int i = 0; i< ROW; ++i)
17     {
18         for (int j = 0; j < COL; ++j)
19         {
20             p[i][j] = i + j;
21         }
22     }
23     for (int i = 0; i< ROW; ++i)
24     {
25         for (int j = 0; j < COL; ++j)
26         {
27             cout << p[i][j]<<" ";
28         }
29         cout << endl;
30     }
31     for (int i=0;i<ROW;++i)
32     {
33         free(p[i]);
34     }
35     free(p);
36     return 0;
37 }
View Code

代碼封裝一下,malloc版本

 1 #include<iostream>
 2 #include<assert.h>
 3 using namespace std;
 4 #define Type int
 5 #define ROW 3
 6 #define COL 4
 7 
 8 Type** _Malloc(int row,int col)
 9 {
10     Type **p = (Type**)malloc(sizeof(Type*)*row);
11     assert(NULL != p);
12     for (int i = 0; i<row; ++i)
13     {
14         p[i] = (Type*)malloc(sizeof(Type)*col);
15         assert(NULL != p[i]);
16     }
17     return p;
18 }
19 
20 void _Assign(Type **p, int row, int col)
21 {
22     for (int i = 0; i< row; ++i)
23     {
24         for (int j = 0; j < col; ++j)
25         {
26             p[i][j] = i + j;
27         }
28     }
29 }
30 
31 void _Print(Type **p, int row, int col)
32 {
33     for (int i = 0; i< row; ++i)
34     {
35         for (int j = 0; j < col; ++j)
36         {
37             cout << p[i][j] << " ";
38         }
39         cout << endl;
40     }
41 }
42 
43 void _Free(Type **p, int row)
44 {
45     for (int i = 0; i<row; ++i)
46     {
47         free(p[i]);
48     }
49     free(p);
50 }
51 int main()
52 {
53     Type **p = _Malloc(ROW,COL);
54     _Assign(p,ROW,COL);
55     _Print(p, ROW, COL);
56     _Free(p, ROW);
57     return 0;
58 }
View Code

new版本

 1 #include<iostream>
 2 #include<assert.h>
 3 using namespace std;
 4 #define Type int
 5 #define ROW 3
 6 #define COL 4
 7 
 8 Type** _New(int row,int col)
 9 {
10     Type **p = new Type*[row];
11     assert(NULL != p); //C++一般不用斷言,而是使用異常機制
12     for (int i = 0; i<row; ++i)
13     {
14         p[i] = new Type[col];
15         assert(NULL != p[i]);
16     }
17     return p;
18 }
19 
20 void _Assign(Type **p, int row, int col)
21 {
22     for (int i = 0; i< row; ++i)
23     {
24         for (int j = 0; j < col; ++j)
25         {
26             p[i][j] = i + j;
27         }
28     }
29 }
30 
31 void _Print(Type **p, int row, int col)
32 {
33     for (int i = 0; i< row; ++i)
34     {
35         for (int j = 0; j < col; ++j)
36         {
37             cout << p[i][j] << " ";
38         }
39         cout << endl;
40     }
41 }
42 
43 void _Delete(Type **p, int row)
44 {
45     for (int i = 0; i<row; ++i)
46     {
47         delete []p[i];
48     }
49     delete []p;
50 }
51 int main()
52 {
53     Type **p = _New(ROW,COL);
54     _Assign(p,ROW,COL);
55     _Print(p, ROW, COL);
56     _Delete(p, ROW);
57     return 0;
58 }
View Code

C++的常用做法

在C++里面開辟二維數組,實際上沒有上面那么麻煩。在看懂下面代碼之前,需要向理解下面的思想。

數組的首元數是誰,指向數組首元素的指針真么寫?

對於一維數組,如下圖,首元素就是整型。整型數組首元素的地址就是int*。所以一維數組接收地址就是一個整型指針int*。

對於二維數組,必然涉及到行和列,他的首元素就不再是其中單獨一行的某一個元數,而是整體一行,首元素的地址就是(一維數組的地址)int**。所以二位數組接收地址就是int**,也就是說需要使用int**指向首元素,因為首元素是一維數組,數組是int*類型。

二維數組代碼演示

 1 #include<iostream>
 2 #include<assert.h>
 3 using namespace std;
 4 #define Type int
 5 #define ROW 3
 6 #define COL 4
 7 
 8 //定義數組指針類型
 9 typedef Type(*Ar)[COL];
10 Ar _New()
11 {
12     Ar p= new Type[ROW][COL];
13     return p;
14 }
15 
16 void _Assign(Ar p, int row, int col)
17 {
18     for (int i = 0; i< row; ++i)
19     {
20         for (int j = 0; j < col; ++j)
21         {
22             p[i][j] = i + j;
23         }
24     }
25 }
26 
27 void _Print(Ar p, int row, int col)
28 {
29     for (int i = 0; i< row; ++i)
30     {
31         for (int j = 0; j < col; ++j)
32         {
33             cout << p[i][j] << " ";
34         }
35         cout << endl;
36     }
37 }
38 
39 void _Delete(Ar p)
40 {
41     delete []p;
42 }
43 int main()
44 {
45     Ar p = _New();
46     _Assign(p,ROW,COL);
47     _Print(p, ROW, COL);
48     _Delete(p);
49     return 0;
50 }
View Code

三維數組代碼演示

 1 #include<iostream>
 2 #include<assert.h>
 3 using namespace std;
 4 #define Type int
 5 #define ROW 3
 6 #define COL 4
 7 #define Z 5
 8 
 9 //定義數組指針類型
10 typedef Type(*Ar)[ROW][COL];
11 Ar _New()
12 {
13     Ar p = new Type[Z][ROW][COL];
14     return p;
15 }
16 
17 void _Assign(Ar p, int row, int col, int z)
18 {
19     static int count = 0;
20     for (int i = 0; i < row; ++i)
21     {
22         for (int j = 0; j < col; ++j)
23         {
24             for (int k = 0; k < z; ++k)
25             {
26                 p[i][j][k] = ++count;
27                 cout.width(5);
28                 cout.flags(ios::left);
29                 cout << p[i][j][k] << " ";
30             }
31             cout << endl;
32         }
33         cout << endl;
34     }
35 }
36 
37 void _Print(Ar p, int row, int col, int z)
38 {
39     for (int k = 0; k < z; ++k)
40     {
41         for (int i = 0; i < row; ++i)
42         {
43             for (int j = 0; j < col; ++j)
44             {
45                 cout.width(5);
46                 cout.flags(ios::left);
47                 cout << p[i][j][k] << " ";
48             }
49             cout << endl;
50         }
51         cout << endl;
52     }
53 }
54 
55 void _Delete(Ar p)
56 {
57     delete[]p;
58 }
59 int main()
60 {
61     Ar p = _New();
62     _Assign(p, ROW, COL, Z);
63     _Print(p, ROW, COL, Z);
64     _Delete(p);
65     return 0;
66 }
View Code

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM