内存泄漏(臭名昭著的Bug)

  • 动态内存申请堆空间,用完后不归还
  • C++ 语言中没有垃圾回收的机制
  • 指针无法控制所指堆空间的生命周期

当代C++软件平台中的智能指针

  • 指针生命周期结束时主动释放堆空间
  • 一片堆空间最多只能由一个指针标识
  • 杜绝指针运算和指针比较

智能指针的设计方案

  • 通过类模板描述指针的行为

    • 能够定义不同类型的指针对象
  • 重载指针特征操作符(-> 和 *)

    • 利用对象模拟原生指针的行为

编程实验:智能指针

文件:SmartPointer.h

#ifndef SMARTPOINTER_H
#define SMARTPOINTER_H

namespace DTLib
{
template<typename T>
class SmartPointer
{
public:
    SmartPointer(T *p = nullptr)
    {
        m_pointer = p;
    }

    SmartPointer(const SmartPointer &obj)
    {
        m_pointer = obj.m_pointer;
        const_cast<SmartPointer&>(obj).m_pointer = nullptr;
    }

    SmartPointer &operator = (const SmartPointer &obj)
    {
        if (this != &obj)
        {
            delete m_pointer;
            m_pointer = obj.m_pointer;
            const_cast<SmartPointer&>(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;
    }

private:
    T *m_pointer = nullptr;
};
}

#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;
    }

    void print()
    {
        cout << "void print() : " << value << endl;
    }

private:
    int value = 10;
};

int main()
{
    SmartPointer<Test> p1 = new Test();
    SmartPointer<Test> p2(p1);
    cout << "p1 = " << p1.isNull() << endl;
    cout << "p2 = " << p2.isNull() << endl;

    SmartPointer<Test> p3;
    p3 = p2;
    cout << "p2 = " << p2.isNull() << endl;
    cout << "p3 = " << p3.isNull() << endl;

    p3->print();
    (*p3).print();

    return 0;
}

输出:

Test()
p1 = 1
p2 = 0
p2 = 1
p3 = 0
void print() : 10
void print() : 10
~Test()

智能指针的使用军规

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

小结

  • 指针特征操作符 (-> 和 *) 可以被重载
  • 重载指针特征符使用对象代替指针
  • 智能指针只能用于指向堆空间中的内存
  • 智能指针的意义在于最大程度的避免内存问题

以上内容整理于狄泰软件学院系列课程,请大家保护原创!


TianSong
737 声望139 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧