• 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. {  
    4.   
    5. public:  
    6.   
    7.        CBase() { cout <<"CBase is running! ";}  
    8.   
    9.        ~CBase() { cout <<"~CBase() is running! ";}  
    10.   
    11. };  
    12.   
    13.    
    14.   
    15. int main()  
    16.   
    17. {  
    18.   
    19.        //选项B错误  
    20.   
    21.        CBase * pBase = new CBase; //调用构造函数  
    22.   
    23.        void * pVoid = (void *)pBase;  
    24.   
    25.        delete pVoid; //肯定不會調用类A的析构函数  
    26.   
    27.    
    28.   
    29.        //选项D错误  
    30.   
    31.        CBase *pBaseN = newCBase[100]; //调用构造函数100次  
    32.   
    33.        delete []pBaseN; //调用析构函数100次  
    34.   
    35.    
    36.   
    37.        return 0;  
    38.   
    39. }  


     

    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.   
    8.     for(int i=0;i<nLength;i++)  
    9.     {  
    10.         pDescStr2[nLength-i-1]=pSourceStr[i];  
    11.     }  
    12.   
    13.     //结束前并没有释放pDescStr2所指向的内存空间  
    14.     return pDescStr2;  
    15.     //只是释放了pDescStr这个指针  
    16. }  
    17. void main()  
    18. {  
    19.   
    20.     char pSourceStr[]={"abcdefghijk"};  
    21.     cout<<"The source string:  "<<pSourceStr<<endl;  
    22.   
    23.     //新建一个指向ReverseString()函数中申请到的内存的指针  
    24.     char* pDescStr=ReverseString(pSourceStr,strlen(pSourceStr));  
    25.     cout<<"The desc string:  "<<pDescStr<<endl;  
    26.   
    27.     //在这里释放ReverseString()函数中申请到的内存  
    28.     delete[] pDescStr;  
    29.     //清除pDescStr指针,以免在今后的使用中出现溢出  
    30.     pDescStr=NULL;  
    31. }  


     

    从上面的例子可以看出,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

  • 相关阅读:
    关于Shipping
    怎么Debug Background Job [转载sdn]
    如何显示IDoc的每个segment/field的具体说明
    underscore.js
    Javascript Style Guide
    [转] Ajax_XMLHttpRequest对象详解
    ExecutingMethodsFromLinkButtonParameters
    使用C#操作MSExcel表格COM
    [转]HttpContext, HttpModules 和 HttpHandlers
    几个实用的Servlet应用例子入门、cookie、session及上传文件
  • 原文地址:https://www.cnblogs.com/findumars/p/6417936.html
Copyright © 2020-2023  润新知