zoukankan      html  css  js  c++  java
  • 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

     

     

  • 相关阅读:
    nginx反向代理编译异常
    TCP/ip协议栈之内核调优
    Tcp之异常
    Codeforces Round #584
    Codeforces Round #588 (Div. 2)
    Codeforces Round #587 (Div. 3) F
    P4587 [FJOI2016]神秘数 主席树
    P4559 [JSOI2018]列队 主席树
    P4098 [HEOI2013]ALO 可持久化01trie
    4771: 七彩树 主席树
  • 原文地址:https://www.cnblogs.com/kelamoyujuzhen/p/9575324.html
Copyright © 2011-2022 走看看