new和delete必须成对出现吗?【网上集合贴+个人总结】

1.从内存泄露与否的角度考虑

new 和 delete不一定要成对出現。理论上是這樣的。但是从习惯上來說,new delete成對出現是一個好的習慣。爲什麽說不一定要成對出現呢?

这个问题在csdn上有一個牛人写过很长的文章,不知道有沒有人还能找到?我記得大概是這個意思。

(1)认为一定要成对出現的,主要是因为动态分配内存之后,如果不释放,会造成内存泄露。

(2)但是,实际上并不总是如此。从操作系统角度上說,内存不能释放,是因为原先指向該内存块的指针丟失了,(比如該指針指向了另一块内存)。这样的情況下,才会造成内存泄露。但是,如果使用了new分配了一块内存,但是指向該内存的指针一直在,一直指向該内存,那麽在程序结束的時候,系統会自动把該指針指向的内存释放掉,從操作系統角度上說,並沒有造成内存洩露。

所以,new和 delete客观的來説,並不一定需要成對出現。我们对内存泄露的真正含義理解的並不是很正确。

這是我看了那個牛人的文章后的体会,那篇文章中有不少例子和數据,還有编译結果解释。非常好,可惜我記不得題目了,沒找到,在這裡說說我的理解。

2.某选择题选项B、D

B,若P的类型由A强制转换为void*,那么执行语句delete P*时,类A的析构函数不会被调用

D,执行语句 A*P=new A[100]时,类A的构造函数只会被调用一次

  1. class CBase
  2. {
  3. public:
  4. CBase() { cout <<"CBase is running!\n";}
  5. ~CBase() { cout <<"~CBase() is running!\n";}
  6. };
  7. int main()
  8. {
  9. //选项B错误
  10. CBase * pBase = new CBase; //调用构造函数
  11. void * pVoid = (void *)pBase;
  12. delete pVoid; //肯定不會調用类A的析构函数
  13. //选项D错误
  14. CBase *pBaseN = newCBase[100]; //调用构造函数100次
  15. delete []pBaseN; //调用析构函数100次
  16. return 0;
  17. }

3. C++内存分配之NEW DELETE

1)new 和 delete 必须成对出现;——此处观点值得商榷

2)new底层调用操作系统堆内存管理函数HeapAlloc来分配堆内存;

3)delete操作符底层调用API接口函数HeapFree来释放堆内存;

数据的3种存储方式。

1。静态区:全局变量或者使用static约束的变量;

2。堆:程序执行时分配的内存;如new操作所分配的动态内存

3。栈:函数调用,局部变量。

以上3种方式的区别:注意,堆上分配的内存不会被操作系统自动回收。

以下为常见的动态内存调用和销毁:

语句一: int * pt;

语句二: pt = new int;

语句三: delete pt;

分步详解:

语句一:你声明了一个pt指针,四个字节,放在栈里面的(pt为局部变量,所属栈内存区域);

语句二:你new了一个int形的数据放在堆里面,再把这个数据的地址赋给pt。(动态分配内存,所属堆内存区域);

语句三:把pt指向的地址所占的内存释放掉。

1.释放的就是堆上面的那个int(动态销毁内存,所属堆内存区域数据销毁)

2.pt还是存在的,还在栈里面。不过你查它的值时,变成了null。(pt为局部变量,所属栈内存区域,由操作系统自行销毁)。

如果能够明白以上内容,就可以避免编程过程中的许多问题和疑惑。

4. 实例角度分析

我记得当年学习C++基础的时候,老师曾经告诉我们:一般来说new和delete要成对出现,在使用完new申请的内存后要马上释放。我相信持这种说法的人不止我们老师一个人,养成良好的内存使用习惯固然重要,但如果因此就认为new和delete必须成对出现,使用完new得到的空间后就要马上用delete释放的话,就有点“大材小用”了,相信C++提供这一由用户控制的内存控制方法也不是只限于如此的使用方法。

正确灵活的,或许也是“高级”的使用方法,是在A处使用new申请一块内存,用一个指针指pA向它,之后在B处用指针pB指向pA所指向的空间,释放指针pA本身,接着释放pB所指向的内存空间,最后释放指针pB本身。

以下的代码是本过程的一个例子:

  1. #include<iostream.h>
  2. #include<string.h>
  3. char* ReverseString(char* pSourceStr,int nLength)
  4. {
  5. //这里在堆上动态申请了一个长度为nLength的内存空间pDescStr2
  6. char* pDescStr2=new char[nLength];
  7. for(int i=0;i<nLength;i++)
  8. {
  9. pDescStr2[nLength-i-1]=pSourceStr[i];
  10. }
  11. //结束前并没有释放pDescStr2所指向的内存空间
  12. return pDescStr2;
  13. //只是释放了pDescStr这个指针
  14. }
  15. void main()
  16. {
  17. char pSourceStr[]={"abcdefghijk"};
  18. cout<<"The source string: \t"<<pSourceStr<<endl;
  19. //新建一个指向ReverseString()函数中申请到的内存的指针
  20. char* pDescStr=ReverseString(pSourceStr,strlen(pSourceStr));
  21. cout<<"The desc string: \t"<<pDescStr<<endl;
  22. //在这里释放ReverseString()函数中申请到的内存
  23. delete[] pDescStr;
  24. //清除pDescStr指针,以免在今后的使用中出现溢出
  25. pDescStr=NULL;
  26. }

从上面的例子可以看出,new和delete并没有在同一个函数中出现,但是很明显这样做没有造成内存泄露(memory leak)。

或许这样使用new和delete有点小儿科,达到ReverseString()函数的目的完全可以不必使用new和delete。我认为new和delete最大的用武之地是在线程通信和进程通信中:比如线程A要向线程B投递一条信息,并要求不等线程B做出反应线程A就要马上进行后面的操作,也就是要求使用PostMessage(...)函数来投递消息,而且发送的消息内容存储在一个50K或者更大的内存空间中,那就必须使用new和delete了,也就是在线程A中用new准备好这样一个庞大的消息,之后把指针发送给进程B,进程B在处理完消息之后用delete释放这块内存。

总而言之,new和delete并非我们想像的那么简单,除了我所提到的用处之外还有不少其他的用处,有待研究,希望与大家探讨。

http://blog.csdn.net/laoyang360/article/details/7765308

new和delete必须成对出现吗?【网上集合贴+个人总结】的更多相关文章

  1. 很多人以为 connect 和 disconnect 应该像 new 和 delete 一样成对出现 这是错误的(只要 sender 或 receiver 其中之一不存在了,connect 会自动失效。QObject::connect 函数是线程安全的)

    其实我写文章也是边查资料边编辑的 有时候是怕自己的阐述不严谨,有时候是怕自己重复造轮子 就像有些人不停的教大家QLabel QDialog QWidget 个人是不屑的 命令模式 用 Qt's Und ...

  2. asp.net mvc(一) ----------简单封装成通用的List<T>集合

    asp.net mvc(一) 这些天开始学习asp.net mvc,用传统的asp.net已经快四的年了,刚开始接触asp.net mvc确认感觉有点不适应,主要体现在asp.net mvc的实现上. ...

  3. 条款16:成对使用new和delete时,采取相同的形式

    问题聚焦:     我们都知道,new和delete要成对使用,但是有时候,事情往往不是按我们预期的那样发展.     对于单一对象和对象数组,我们要分开考虑.     遇到typedef时,也需要搞 ...

  4. Effective C++(16) 成对使用new和delete时要采取相同的形式

      问题聚焦:     我们都知道,new和delete要成对使用,但是有时候,事情往往不是按我们预期的那样发展.     对于单一对象和对象数组,我们要分开考虑     遇到typedef时,也需要 ...

  5. Android项目实战(二十四):项目包成jar文件,并且将工程中引用的jar一起打入新的jar文件中

    前言: 关于.jar文件: 平时我们Android项目开发中经常会用到第三方的.jar文件. 其实.jar文件就是一个类似.zip文件的压缩包,里面包含了一些源代码,注意的是.jar不包含资源文件(r ...

  6. new和delete malloc和free

    程序中动态分配的对象存放在自由存储区(free store)或堆(heap). C语言程序使用一对标准库函数malloc和free在自由存储区中分配存储空间,而C++语言则使用new和delete表达 ...

  7. 关于new 和delete

    这是百度知道上的答案,感觉讲的很生动形象,接下来要搞清楚的是new是关键字还是函数,new可以重载吗? 你想弄懂这个问题,首先你要弄清楚数据的3种存储方式. 1.静态区: 全局变量. 2.堆: 程序执 ...

  8. 浅谈new/delete和malloc/free的用法与区别

    每个程序在执行时都会占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为自由存储区或堆. 一.new和delete用法 如下几行代码: int *pi=new int; int *pi=ne ...

  9. Electron把网页打包成桌面应用并进行源码加密

    前言 最近想把自己用html+css+js做的网页界面打包成桌面应用,网上一搜,发现Electron是一个不错的选择,试了试,发现效果真的不错.这里记录一下打包过程以作记录,便于自己以后查看学习. 一 ...

随机推荐

  1. C# Tuple VS ValueTuple

    C# Tuple VS ValueTuple(元组类 VS 值元组) C# 7.0已经出来一段时间了,大家都知道新特性里面有个对元组的优化:ValueTuple.这里利用详尽的例子详解Tuple VS ...

  2. Scala入门到精通——第二十七节 Scala操纵XML

    本节主要内容 XML 字面量 XML内容提取 XML对象序列化及反序列化 XML文件读取与保存 XML模式匹配 1. XML 字面量 XML是一种很重要的半结构化数据表示方式,眼下大量的应用依赖于XM ...

  3. Access control differentiation in trusted computer system

    A trusted computer system that offers Linux® compatibility and supports contemporary hardware speeds ...

  4. linux 网卡配置文件详解

    配置文件位置:/etc/sysconfig/network-scripts/ifcfg-eth0 1. DEVICE=eth0 网卡的名字 2. HWADDR=00:0c:29:90:89:d9 HW ...

  5. hibernate annotation 相关主键生成策略

    Hibernate 默认的全面支持 13 物种生成策略 : 1. increment 2.  identity 3. sequence 4. hilo 5. seqhilo 6. uuid 7. uu ...

  6. Live Unit Testing

    Live Unit Testing 相对于传统的Unit Test,VS2017 带来了一个新的功能,叫Live Unit Testing,从字面意思理解就是实时单元测试,在实际的使用中,这个功能就是 ...

  7. Android Studio 使用教程(二十五)之运行Android Studio工程

    一.Android虚拟设备入口 上期我们使用了Android Studio创建了HeloWorld工程,要想运行该工程,首先需要一个Android虚拟设备来模拟Android程序的运行. 重新打开An ...

  8. JAVA从本机获取IP地址

    JAVA从本机获取IP地址 论述: 此篇博客是在工作的时候,需要获得当前网络下面正确的ip地址,在网上查阅很多博客,网上一个比较普遍的说法是通过InetAddress.getLocalHost().g ...

  9. 链表Linked List

    链表Linked List 1. 链表 数组是一种顺序表,index与value之间是一种顺序映射,以O(1)O(1)的复杂度访问数据元素.但是,若要在表的中间部分插入(或删除)某一个元素时,需要将后 ...

  10. SWIFT学习笔记02

    1.//下面的浮点文字等于十进制12.1875: let decimalDouble = 12.1875 let exponentDouble = 1.21875e1 let hexadecimalD ...