C++动态分配内存

[来源] 达内    [编辑] 达内   [时间]2012-10-12

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

  数组是我们常用的一种数据结构.但它有一个缺点,就是用的时候必须确定数组大小.如果我们要用数组来保存的数据不确定可咋整啊?把数组定得太大浪费空间,太小的话又装不下.这是一种情况.另外就是对象太大.我们使用的数据大部分时候都默认保存在栈(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.

资源下载