第9课

内存泄漏

  -动态申请堆空间,用完后不归还

  -c++语言中没有垃圾回收机制

  -指针无法控制所指堆空间的生命周期

代码练兵场:

#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H

namespace DTLib
{
    template<typename T>
    class SmartPointer
    {
    public:
        SmartPointer(T *p=nullptr)
        {
            m_pointer=p;
        }
        SmartPointer(const SmartPointer<T>& obj)
        {
            m_pointer=obj.m_pointer;
            const_cast<SmartPointer<T>&>(obj).m_pointer=nullptr;
        }
        SmartPointer<T>& operator =(const SmartPointer<T>& obj)
        {
            if(this!=&obj)
            {
                delete m_pointer;//一定要先释放之前指向的空间,虽然可能delete一个null指针让我们觉得有点怪异,比如默认初始化sp,然后把p赋值给sp,此时delete的是null,但是程序是没有害处的、要是想要完全合乎new和delete配对,可以在这个delete前加一个if判断,如果非NULL,就delete
                m_pointer=obj.m_pointer;
                const_cast<SmartPointer<T>&>(obj).m_pointer=nullptr;
            }
            return *this;
        }
        T *operator->()
        {
            return m_pointer;
        }
        T &operator*()
        {
            return *m_pointer;
        }
        bool isNull()
        {
            return (m_pointer==nullptr);
        }
        T *get()
        {
            return m_pointer;
        }
        ~SmartPointer()
        {
            delete m_pointer;
        }
    protected:
        T *m_pointer;
    };
}
#endif // SMARTPOINTER_H

main.cpp:

#include <iostream>
#include "smartpointer.h"
using namespace std;
using namespace DTLib;

class Test
{
public:
    Test()
    {
        cout<<" Test()"<<endl;
    }
    ~Test()
    {
        cout<<" ~Test()"<<endl;
    }
};
int main()
{
   SmartPointer<Test> p= new Test();
   SmartPointer<Test> sp=p;
  // sp=p;
   //sp++;
   cout<<p.isNull()<<endl;
   cout<<sp.isNull()<<endl;
    return 0;
}

输出:

 代码知识点解释:

 

const_cast<SmartPointer<T>&>(obj).m_pointer=nullptr;,在拷贝构造函数中,obj是const的,内容不允许修改,但是我们的智能指针设计需求第二步,开辟的堆空间,只能有一个指针标识,所以我想去掉obj类中的指针成员的指向,使用强制类型转化,去掉obj类的const属性,注意obj是我们要去const化的,而不是obj.m_pointer。同样的道理,我们需要重载赋值运算符,在不是自赋值的情况下,满足重载赋值运算符的if条件(针对上面的代码而言),释放this的m_pointer指向的内存,把obj的指针赋值给this的m_pointer,再把obj的m_pointer指针置成null,这样还是为了只给一个指针标识。然后重载了->和解引用*操作符。在main.cpp中,我们创建了一个Test类,用智能指针指向这个new出来的类,再把p指针用了初始化sp(将调用拷贝构造函数),此时,首先打印Test的无参构造函数,然后p初始化了sp,故p的m_pointer应该被置成了null,所以isNull函数返回1,但是sp此时接管Test类的内存,所以sp的isNull返回0,非空。最后Test类析构,智能指针指向的内存也会因为调用了自己的析构函数释放内存。在我们实现的智能指针中,是不运行执行指针和比较的,执行++这种操作是没有定义的,符合之前我们提到的智能指针三个要求。c++11中,建议用nullptr代替NULL。

 NOTE:

智能指针用来指向堆空间中的单个对象或者变量。

原文地址:https://www.cnblogs.com/yangguang-it/p/7195819.html