找回密码
 立即注册

C++老鸟日记039 关于delete的丁点常识

累计签到:40 天
连续签到:1 天
发表于 2018-10-12 09:01:02 | 显示全部楼层 |阅读模式
本帖最后由 baizy77 于 2018-10-12 11:40 编辑

版权声明
---------------------------------------------------------------------------------------------------------------------
该文章原创于Qter开源社区(www.qter.org
作者: 女儿叫老白 (白振勇)
转载请注明出处!
---------------------------------------------------------------------------------------------------------------------
本套课程属于:《C++跨平台开发干货》系列课程。
---------------------------------------------------------------------------------------------------------------------


引言:
----------------------------------------------------------------------------
       本文主要内容引自《C++编程思想》(注1)。
       今天我们介绍一点delete的知识,虽然比较简单,但还是需要引起大家的注意。

正文:
----------------------------------------------------------------------------
       首先介绍一个常识,在使用指针时,如果指针被赋值指向一块new出的内存,当使用完毕后,我们会将指针delete,delete之后请将指针赋值为NULL。这是防止将一个对象删除两次的一个有效方法,比如:
代码清单:
  1. ----------------------------------------------------------------------------
  2. // func.cpp
  3. void CPlayWorld::func(void) {
  4. m_pMyClassObject = new CMyClass();
  5.        ……
  6.        if (NULL != m_pMyClassObject) {
  7.            delete m_pMyClassObject;
  8.            m_pMyClassObject = NULL;
  9.       }
  10.       ……
  11. ----------------------------------------------------------------------------
复制代码

       有时候,我们在编程时会用到void*指针,那么对void*指针进行delete操作是安全的吗?
代码清单:
  1. ----------------------------------------------------------------------------
  2. // myclass.h
  3. class CMyClass {
  4. public:
  5.     CMyClass(int size);
  6.     ~CMyClass();

  7. private:
  8.     int m_nSize;
  9.     void* m_pData;
  10. };

  11. // myclass.cpp
  12. #include <iostream>
  13. using std::cout;
  14. using std::endl;

  15. CMyClass::CMyClass(int size):m_nSize(size) {
  16.     if (m_nSize>0) {
  17.         m_pData = new char[m_nSzie];
  18.         cout << “正在构造…” << endl;
  19.     }
  20. }

  21. CMyClass::~CMyClass()  {
  22.     if (NULL != m_pData) {
  23.         delete[] m_pData;
  24.         m_pData = NULL;
  25.     }

  26.     cout << “正在析构…”<<endl;
  27. }

  28. // main.cpp
  29. int main(int argc, char* argv[]) {
  30.     CMyClass* pObj = new CMyClass(20);
  31.     if (NULL != pObj) {
  32.         delete pObj;
  33.         pObj = NULL;
  34.     }

  35.     void* pVoidObj = new CMyClass(20);
  36.     if (NULL != pVoidObj) {
  37.         delete pVoidObj;
  38.         pVoidObj = NULL;
  39.     }
  40. }
  41. ----------------------------------------------------------------------------
复制代码

       类CMyClass含有一个void*指针m_pData, 在构造函数中它被赋值指向一块“元”数据区,在析构函数中delete[] m_pData可以把内存释放,因为m_pData并没有指向对象,而仅仅指向一块原生数据块。
       但在main()函数中,情况就不同了,我们看到使delete知道它所操作的类型是十分必要的。上述代码的输出信息如下:
       正在构造…
       正在析构…
       正在构造…
       当delete pObj时,编译器知道pObj是指向CMyClass类型对象的指针,所以它会调用对象的析构函数,所有内存都会正确释放;而delete pVoidObj时,编译器知道的是在delete一个void*指针,它并不知道pVoidObj指向对象的确切类型,所以它仅仅把pVoidObj对象的内存释放,而不会调用pVoidObj所指向对象的析构函数,这样就造成了内存泄漏。
最后是一个老生常谈的问题,就是要根据对象的个数确定到底使用delete 还是delete[]。即使是编程老手有时也难免疏忽,因此请大家一定要重视。

结语:
----------------------------------------------------------------------------
       本文的内容介绍了delete的一点知识,主要内容引自《C++编程思想》两卷合订本。编写本文的目的主要是小编认为这些还是比较重要的,希望引起大家对语法细节的注意。

参考资料
----------------------------------------------------------------------------
注1:《C++编程思想》两卷合订本中文版(第13章),(美) Bruce Eckel  Chuck Allison著


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

baizy77

    主题

    帖子

    181

    积分

    Qter2级会员

    Rank: 2

    积分
    181

Qter2级会员

发私信

Qt开源社区——开源 共享 自由

微信扫一扫
查看精品教程!