new和delete表达式可以用来动态创建和释放单个对象,也可以用来动态创建和释放动态数组。

  定义变量时,必须指定其数据类型和名字。而动态创建对象时,只需指定其数据类型,而不必为该对象命名。new表达式返回指向新创建对象的指针,我们通过该指针访问对象:

  1. int i; //named, uninitizlized int variable
  2. int *pi = new int; //pi points to dynamically allocated unnamed int
 
   这个new表达式在堆内分配创建了一个整形对象,并返回对象的地址,并用该地址初始化指针pi。
   如果new失败,抛出标准异常std::bad_alloc异常。
 
  1. 动态创建对象的初始化
   动态创建的对象可以初始化变量的方式实现初始化:
   

  1. int i(); //value of i is 1024
  2. int *pi = new int(); //object to which pi is 1024
  3. string s(,''); //value of s is '9999999999'
  4. string *ps = new string(, ''); //*ps is '9999999999'

C++使用值初始化的方式语法规则初始化动态创建的对象。如果提供了初值,new表达式分配到所需要内存后,用给定的初值初始化该内存。

  2. 动态创建对象的默认初始化

    如果不显式初始化。动态创建的对象与在函数内定义的变量初始化方式相同。对于类类型对象,用该类的默认构造函数初始化;而内置类型的对象则无初始化

  1. string *ps = new string; //initialized to empty string
  2. int *pi = new int; //pi points to uninitialized int

   正如我们几乎总要初始化定义为变量的对象一样,在动态创建对象时,(几乎)总是对它做初始化也是一个好方法。

   同样也可以对动态创建的对象做值初始化,规则是:对于类类型对象,调用该类的默认构造函数;内置类型初始化为0;

  1. string *ps = new string() //initialized to empty string
  2. int *pi = new int(); //pi points to int value-initialized to 0
  3. cls *ps = new cls(); //pc points to value-initialized object of type cls

   可以看出,对于类类型的对象,无论程序是明确地不初始化还是要求进行初始化,都会自动调用其默认构造函数初始化该对象。而对于内置类型或没有定义默认构造函数的类型,采用不同初始化方式则有明显的差别:

  1. int *pi = new int; //pi points to uninitialized int
  2. int *pi = new int(); //pi points to an int value-initialized to 0

第一个语句的int型变量没有初始化,而第二个语句的int型变量初始化为0。

   
  3. 撤销动态创建的对象
    动态创建的对象用完后,程序员必须显式地将对象占用的内存返回给堆。C++提供了delete表达式释放指针所指向的地址空间
    delete pi; //该命令释放pi指向的int型对象所占用的空间,指针本身仍然存在,只是内存空间被回收。
    
    如果指针指向的不是new分配的内存地址,则该指针上使用delete是不合法的。例如,
    int i ;
    int *pi = &i;
      delete pi; 
   上述语句是错误的,i是分配在栈上,栈上的内存不需也不能调用delete删除。
  4. 零值指针的删除
    如果指针的值为0,则在其上做delete操作是合法的,但这样做没有任何意义:
  1. int *ip = ;
  2. delete pi; //ok: always ok to delete a pointer that is equal to 0

  5. 在delete之后,重设指针的值

    执行语句 delete p; 后,p变成没有定义。在很多机器上,尽管p没有定义, 但仍然存放了它之前所指向对象的地址,然而p所指向的内存已经释放,因此p不再有效。

    删除指针后,该指针编程悬垂指针。悬垂指针指向曾经存放对象的内存,但该对象已经不存在了。悬垂指针往往导致程序错误,而且很检测出来。

    一旦删除了指针指向的对象,立即将指针置为0,这样就非常清楚地表明指针不再指向任何对象。

  6.动态内存的管理、

  (1)删除指向动态分配内存的指针失败,因为无法将该块内存返回给自由存储区,删除动态分配内存失败称为“内存泄露”。内存泄露很难发现,一般需要等应用程序运行一段时间后,耗尽了所有内存空间时,内存泄露才会显露出来。

  (2)读写已删除的对象,如果删除指针所指向的对象之后,将指针置为0,则比较容易检测出这类错误。、

  (3)对同一内存空间使用两次delete表达式。当两个指针指向同一个动态创建的对象,删除就会发生错误,如果在其中一个指针上做delete运算,则该对象的内存空间返回给自由存储区,然后接着delete第二个指针,此时则自由存储区可能被破坏。

  7. new和delete的底层原理

       当你使用new时,有两件事情发生。第一,内存被分配出来(通过operator new的函数)。第二,针对此内存会有一个(或更多)构造函数被调用。

    当你使用delete时,也有两件事情发生:针对此内存会有一个(或更多)的析构函数被调用,然后内存才能被释放(通过名为:operator delete的函数)。

    
创建动态数组:
  数组类型的变量有三个变量的限制:数组长度固定不变,在编译时必须知道其长度,数组在定义它的块语句内存在。  
  1. 动态数组的定义
      new表达式需要指定指针类型以及在方括号中给出的数组维数,该维数可以是任意的复杂表达式。创建数组后,new 将返回指向数组第一个元素的指针。在堆中创建的数组对象时没有名字的,程序员只能通过其间接地访问堆中的对象。
     int *pia = new int[10];、
 
   2. 初始化动态分配的数组
    动态分配时,如果数组元素具有类类型,将使用该类型的默认构造函数实现初始化;如果数组元素是内置类型,则无初始化。也可使用跟在数组长度后面的一对空括号,对数组元素做值初始化:
    int *pia2 = new int[10]();  //array of 10 uninitialized ints
    圆括号要求编译器对数组做值初始化,在本例中即把数组元素都设置为0。
    
    对于动态分配的数组,其元素只能初始化为元素类型的默认值,而不能像数组变量一样,用初始化列表为数组元素提供各不相同的初值。

    
   3. 动态空间的释放

    动态分配的空间必须释放,否则,内存最终将会被耗尽。如果不再需要使用动态创建的数组,程序员必须显式地将其占用的存储空间返回给程序的堆区。C++语言为指针提供了delete[] 表达式释放指针所指向的数组空间:

    delete []pia;

    该语句回收了pia所指向的数组,把相应的内存返回给堆。在关键字delete和指针之间的方括号是必不可少的;它告诉编译器该指针指向的是堆区的数组,而并非是单个对象。

    理论上,回收数组时缺少方括号对,至少会导致运行时少释放了内存空间,从而产生内存泄露。对于某些系统或元素类型,有可能会带来更严重的运行时错误。因此,在释放动态内存时千万不能忘了方括号对

    更多解释详见《Effective C++》条款16。

  malloc/free和new/delete的区别:

  1) malloc和free是C/C++语言的标准库函数,new/delete是C++的运算符。

  2) malloc/free需要库文件支持,new/delete不需要。

  3) new自动计算需要分配空间的大小,malloc需要手工计算字节数

  4)new是类型安全的,而malloc不是,比如:

  1. int* p = new float[]; //编译时指出错误
  2. int* p = (int*)malloc(*sizeof(double)); //编译时无法指出错误

  5)new调用operator new分配足够的空间,并调用相关对象的构造函数,而malloc不能调用构造函数;delete将调用该实例的析构函数,然后调用类的operator delete,以释放该实例占用的空间,而free不能调用析构函数。

【C++】new和delete表达式与内存管理的更多相关文章

  1. 引用计数的cocos2dx对象内存管理和直接new/delete box2d对象内存管理冲突的解决方法

    转载请注明: http://blog.csdn.net/herm_lib/article/details/9316601 项目中用到了cocos2dx和box2d,cocos2dx的内存是基于引用计数 ...

  2. 内存管理运算符new delete与内存管理函数malloc free的区别——已经他们对对象创建的过程。

    (1)内存管理函数与内存管理运算符的区别 内存管理函数有内存分配函数,malloc calloc realloc 以及内存释放函数free. 内存管理运算符有new 和delete. 两种内存管理方式 ...

  3. Cocos2d-x内存管理研究<二>

    http://hi.baidu.com/tzkt623/item/46a26805adf7e938a3332a04   上一篇我们讲了内核是如何将指针加入管理类进行管理.这次我将分析一下内核是如何自动 ...

  4. 【转】C内存管理

    在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重 ...

  5. C++ Primer : 第十二章 : 动态内存之动态内存管理(new和delete)

    C++语言定义了两个运算符来分配和释放动态内存:运算符new分配内存,运算符delete释放new分配的内存. 运算符new和delete 使用new动态分配和初始化对象 在自由空间分配的内存是无名的 ...

  6. 深入理解C++ new/delete, new []/delete[]动态内存管理

    在C语言中,我们写程序时,总是会有动态开辟内存的需求,每到这个时候我们就会想到用malloc/free 去从堆里面动态申请出来一段内存给我们用.但对这一块申请出来的内存,往往还需要我们对它进行稍许的“ ...

  7. C++内存管理(new operator/operator new/operator delete/placement new)

    new operator 我们平时使用的new是new操作符(new operator),就像sizeof一样是语言内置的,不能改变它的含义,功能也是一样的 比如: string *ps = new ...

  8. 深入理解C++中的new/delete和malloc/free动态内存管理

    malloc/free和new/delete的区别 malloc/free是C/C++标准库的函数:new/delete是C++操作符. malloc/free只是动态分配内存空间/释放空间:new/ ...

  9. C++—动态内存管理之深入探究new和delete

    C++中程序存储空间除栈空间和静态区外,每个程序还拥有一个内存池,这部分内存被称为自由空间(free store)或堆(heap).程序用堆来存储动态分配的对象,即,那些程序运行时分配的对象.动态对象 ...

随机推荐

  1. Flex 网络图

    这个是最简单的网络拓扑图开发,我已经帮你把所有拓扑元素封装好,然后直接添加就会具有相关的特性.并且的底层元素也开源,也方便大家oem修改.只需10分钟就可以建设一个完善的拓扑图. 首先下载工程或者SW ...

  2. Mycp补交作业

    Mycp补交作业 代码 import java.io.; import java.lang.; import java.util.Scanner; public class MyCP { public ...

  3. 20155317 王新玮 2006-2007-2 《Java程序设计》第4周学习总结

    20155317 王新玮 2006-2007-2 <Java程序设计>第4周学习总结 教材学习内容总结 第六章 继承共同行为 多个类中存在相同属性和行为时,将这些内容抽取到单独一个类中,那 ...

  4. 20155327 2016-2017-3 《Java程序设计》第4周学习总结

    20155327 2016-2017-3 <Java程序设计>第4周学习总结 教材学习内容总结 一. 理解封装.继承.多态的关系 封装:把客观事物封装成抽象的类,并且类可以把自己的数据和方 ...

  5. 【LG3229】[HNOI2013]旅行

    题面 洛谷 题解 勘误:新的休息点a需要满足的条件2为那一部分小于等于ans 代码 \(100pts\) #include <iostream> #include <cstdio&g ...

  6. P3368 【模板】树状数组 2(区间增减,单点查询)

    P3368 [模板]树状数组 2 题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表 ...

  7. Python:静态方法、类方法、实例方法

    1. 静态方法@staticmethod (1)无需自身对象的self参数和自身类的cls参数,可直接通过 类名.方法名 进行调用 (2)Python中并不是真正意义上的静态方法,因为类定义本身就是个 ...

  8. spring源码-aop-5

    一.在软件业,AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是软件开发 ...

  9. TMS320VC5509驱动LCD1602

    1. 本次使用5509芯片的EMIF接口,先看下硬件的接口 LCD1602接口  RS(高电平1数据寄存器,低电平0指令寄存器) 接A2接口 LCD1602接口  RW(高电平读,低电平写) 接 AW ...

  10. 利用工厂模式实现serviec层和dao层解耦

    利用工厂模式实现serveice和dao层的解耦,这样就可以不用在service层实例化dao层的对象,当dao层代码发生改变的时候(数据库实现发生改变)直接修改配置文件就不用改变service层的代 ...