Fork me on GitHub

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

 

 

 

posted @ 2018-09-02 21:07  克拉默与矩阵  阅读(4239)  评论(0编辑  收藏  举报