C++学习之C++动态分配内存

来源:互联网 发布:旁氏米粹怎么样知乎 编辑:程序博客网 时间:2024/06/07 15:35

为啥需要动态分配内存
     数组是我们常用的一种数据结构.但它有一个缺点,就是用的时候必须确定数组大小.如果我们要用数组来保存的数据不确定可咋整啊?把数组定得太大浪费空间,太小的话又装不下.这是一种情况.另外就是对象太大.我们使用的数据大部分时候都默认保存在栈(stack)里面,由系统去管理,会自动给分配内存,自动给删除掉.但是stack很小,就那么几M,如果你读取一个几十M的文本内容然后保存到一个字符串里,stack肯定会被撑爆了.

     上面说的是两种最常见的两种情景.另外如果你想准确的控制内存的释放.比如内存比较紧缺,你用完一块内存后就想立马释放掉.如果系统自动去释放的话可能得等到变量生命周期结束时再释放.不会做得到立马释放.

     基于上面等一些原因于是出现了堆(heap),这是由用户自己控制的一片内存区,比stack大多了.你可以自由的在里面申请空间释放空间.

C语言中的动态内存分配
C语言是比较接近底层的,用它举例说动态内存的分配更容易理解.C++是作了一定程度的封装.就以数组来举例吧.假如你不知道要使用的数据具体是多少,只要运行的时候才知道.就用N表示需要N个int类型的空间.于是我们需要动态的分配一块内存,并用一个int型指针指向内存的首地址.

int n = 123;    //这里随便赋个值,实际使用时可能是传个参数确定它的值

int * p = (int*)  malloc(sizeof(int)*n);

/*malloc是一个库函数,调用它去申请内存空间,它的返回值是void*指针,所以需要做下类型转换变成int*指针.它的参数是内存大小,以字节为单位,表示要申请多少个字节.int类型可能在不同的系统里占用的字节不一样,所以用sizeof计算下先. 假如你要给结构体分配内存的话,假如有结构体struct  test则是,struct test * pTest = (struct test*) malloc(sizeof(struct test));*/

现在可以把弄来的内存当数组用了.实际上也不是真的数组,只是模拟拉.

int * pArray = p;           //用另一个指针来指向p,因为p要保留着内存的首地址,这样后面释放内存的时候才会正确释放

*pArray = 123;

*(pArray + 1) = 456;

free(p);      //用完了就可以这样来释放内存

p = 0;       //让指针指向一块空内存,这样的好处有,比如你不小心在哪又再free下p就会出错,但让p指向空内存后多次重复free也不会出错.

//free(p)不是释放p指针的内存,而是以它为首地址后面的一大块.它自己保存的地址值还是一直在那,所以你free完了后再打印p保存的地址值还跟以前一样.

C++动态内存分配
  C++中多了个class的概念,而类里面有个比较重要的概念是构造函数.而构造函数不能手动去调用,是实例化类时自动调用.如果像C一样用malloc来给某个类动态分配一块内存的话,这个类就不会调用到构造函数了.于是C++里出现了个关键字new,当你使用new动态一块内存时会自动调用构造函数(这具体咋实现的就不知道了啊.反正最后封装成一个new给我们用).用完了释放的话就用delete,此时会调用析构函数.

举个例子吧假如有类Arwen

Class Arwen

{

   public:

     Arwen(string str){  name = str;}

    string name;

   ~Arwen(){ };

}

 

Arwen weiwen("csharp");    //这样实例化一个类,是由系统在stack中分配内存并释放内存不用我们管

Arwen*  weiwenhp = new Arwen("cplusplus"); //必须用指针Arwen*,这样才是动态内存分配,由用户自己去申请空间去释放空间.

delete weiwenhp;        //释放内存

内存泄露
动态分配内存时最容易犯的错,也是最不容易发现的就是内存泄露了啊.

严格来讲内泄露不是一种错误,它只是没有释放掉申请来的内存,造成了浪费而已.其实很容易用这一点来做一个病毒.你就不停的去申请内存,但都不给释放.到最后内存就会被耗光了.

研究内存泄露是个比较复杂的话题了,会有很多种情况会导致泄露,也有很多方法去防范.

举几个简单的例子瞧下

int * p = new int[88];

delete p;  //这里就内存泄露了,要用delete []p才行.在C中就free(p)就行了

另外在函数中delete还没执行到就退出了也容易内存泄露,比如

int function(int num)

{

         int *p = new[44];

        if( num > 111)

            return 0;

         delete []p; 

return 1;

}

如果num大于100,执行到return 0时就退出了,不会执行到delete.

原创粉丝点击