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

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的构造函数只会被调用一次

[cpp] view plain copy

  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本身。

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

[cpp] view plain copy

  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

时间: 2024-10-17 15:41:33

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

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

问题聚焦: 我们都知道,new和delete要成对使用,但是有时候,事情往往不是按我们预期的那样发展. 对于单一对象和对象数组,我们要分开考虑. 遇到typedef时,也需要搞清楚,是单一对象类型还是对象数组类型. 来看一个例子: std::string* stringArray = new std::string[100]; ... delete stringArray; 问题:stringArray所含的100个string对象中的99个可能并没有被适当地删除,因为它们的析构函数很可能没有被

关于new 和delete

这是百度知道上的答案,感觉讲的很生动形象,接下来要搞清楚的是new是关键字还是函数,new可以重载吗? 你想弄懂这个问题,首先你要弄清楚数据的3种存储方式. 1.静态区: 全局变量. 2.堆: 程序执行是分配的内存 3.栈: 函数调用,局部变量.new出来的内存就是分配到堆上的.程序执行完以后,堆上分配的内存不会被操作系统自动回收,所以你不delete掉的话,操作系统不回收,那块内存就成了没爹没娘的无业有民了,这个就叫内存泄露.我这样说你应该知道为什么书上为什么说new和delete要成对出现了

c++中new和delete的使用

new/ delete 的使用(仅限于c++,注意,new.delete不是函数而是操作符!注意与c中的malloc和free区分)编程的时候经常要用到堆内存的分配,通常使用的操作符是new,这个时候就必然要用到delete去释放申请的内存空间. 此时至少要遵循以下原则: (1)new和delete是成对出现的.只出现一个是错误的或不规范的写法,即使能编译通过,也会有安全隐患: (2)使用的new与delete要相同.也就是说如果你在 new表达式中使用了 [],你必须在对应的 delete 表

优化系列 | DELETE子查询改写优化

0.导读 有个采用子查询的DELETE执行得非常慢,改写成SELECT后执行却很快,最后把这个子查询DELETE改写成JOIN优化过程 1.问题描述 朋友遇到一个怪事,一个用子查询的DELETE,执行效率非常低.把DELETE改成SELECT后执行起来却很快,百思不得其解. 下面就是这个用了子查询的DELETE了: [[email protected]]mydb > EXPLAIN delete from trade_info where id in ( select id from ( sel

使用delete释放new[]的空间造成的错误分析

曲折探索后,这个问题算是水落石出. 我们都被告诫,new和delete,new[]和delete[]要成对出现.如果使用delete 释放new[] 申请的空间会发什么?如下: T* p = new T [1024]; ....//do something delete p;//会发生什么? 我先告诉你,如果T是一个base type(如,int.double.char),你会发现,程序依然正确运行,不仅如此,内存空间也被正确释放.它的正确运行,让很多人对delete[]和delete的区别的探

浅谈new、delete和malloc、free的用法与区别

(1)new和delete用法 如下几行代码: int *pi=new int; int *pi=new int(); int *pi=new int(1024); 第一行这个new表达式在自由存储区中分配创建了一个整形对象,并返回一个指向该对象的地址来初始化指针pi.第二行同一行,只是对指针pi指向的地址的值进行了初始化为0.第三行初始化为1024. 当动态创建的对象用完后必须释放内存,避免造成内存泄漏,可以用delete来完成,new和delete是成对使用的,如下命令释放pi指向的int型

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

前言 最近想把自己用html+css+js做的网页界面打包成桌面应用,网上一搜,发现Electron是一个不错的选择,试了试,发现效果真的不错.这里记录一下打包过程以作记录,便于自己以后查看学习. 一.简介 Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库. Electron通过将Chromium和Node.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的. 二.打包过程 1.

C++进阶--解谜operator new/delete

//############################################################################ // 解谜operator new/delete /* 执行下面代码会发生什么? */ dog* pd = new dog(); /* * Step 1. 调用operator new分配内存 * Step 2. 调用构造函数构造dog * Step 3. 如果第2部抛异常,调用operator delete释放第1步分配的内存 */ de

[转]浅谈new/delete和malloc/free的用法与区别

目录 一.new和delete用法 二.malloc和free的用法 三.new和malloc的区别 正文 每个程序在执行时都会占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为自由存储区或堆. 回到顶部 一.new和delete用法 如下几行代码: int *pi=new int; int *pi=new int(); int *pi=new int(1024); 第一行这个new表达式在自由存储区中分配创建了一个整形对象,并返回一个指向该对象的地址来初始化指针pi.第二行同一行,