第37课 智能指针分析(指针特征操作符( -> 、 *)重载)

1. 永恒的话题:内存泄漏

(1)动态申请堆空间用完后不归还

(2)C++语言中没有垃圾回收的机制

(3)指针无法控制所指堆空间生命周期

 

【编程实验】内存泄漏   37-1.cpp

#include <iostream>

#include "IntArray.h"

 

using namespace std;

 

class Test
{

    int i;

public:

    Test(int i)

    {

        this->i = i;

        cout << "Test(int i)" << endl;

    }

    int value(){return i;}

   

    ~Test()

    {

        cout << "~Test()" << endl;

    }

   

};

 

int main()
{

    for(int i = 0; i < 5; i++)

    {

        Test* p  = new Test(i);

       

        cout << p->value() << endl;

       

        //没有delete p造成内存泄漏

    }

   

    return 0;

}

运行结果:

  

 

 

2. 深度的思考:我们需要什么?

(1)需要一个特殊的指针指针生命期结束时主动释放堆空间

(2)一片堆空间最多只能由一个指针来标识

(3)杜绝指针运算指针比较因为只有一个该类对象的指针能指向堆空间

 

3. 解决方案

(1)重载指针特征操作符( -> 和 * )

(2)只能通过类的成员函数重载

(3)重载函数不能使用参数

(4)只能定义一个重载函数

(5)注意:智能指针只能用来指向堆空间中的对象或变量(不能指向栈)

 

【编程实验】智能指针   37-2.cpp

#include <iostream>

#include "IntArray.h"

 

using namespace std;

 

class Test
{

    int i;

public:

    Test(int i)

    {

        this->i = i;

        cout << "Test(int i)" << endl;

    }

    int value(){return i;}

   

    ~Test()

    {

        cout << "~Test()" << endl;

    }

   

};

 

//定义智能指针类
class Pointer
{

    Test* mp;//用于保存要被管理对象的指针

public:

    Pointer(Test* p = NULL)

    {

        mp = p;

    }

   

    Pointer(const Pointer& obj)

    {

        mp = obj.mp;

       

        //当Pointer p2 = p1时,p1所指的堆空间由p2来接管

        //即保证每次只能有一个智能指针指向同一堆空间

        const_cast<Pointer&>(obj).mp = NULL;

    }

   

    Pointer& operator = (const Pointer& obj)

    {

        if( this != &obj)

        {

            delete mp;

            mp = obj.mp;

            //保证赋值操作时,只能由一个智能指针指向同一堆空间

            const_cast<Pointer&>(obj).mp = NULL;

        }

    }

   

    //重载->操作符

    Test* operator ->() //不能使用参数,所以也就只能定义一个重载函数

    {

        return mp;

    }

   

    //重载*操作符

    Test& operator*()  //不能使用参数,所以也就只能定义一个重载函数

    {

        return *mp;

    }

   

    bool isNull()

    {

        return (mp == NULL);

    }

   

    ~Pointer()

    {

        delete mp;//智能指针被析构时,同时删除其所管理的Test类的对象

    }

};

 

int main()
{

    Pointer p1 = new Test(5);

   

    cout << p1->value() << endl;

   

    Pointer p2 = p1;//p2接管了p1所指的堆空间,保证每次只能由一个智能指针指向堆空间

   

    cout << p1.isNull() << endl;//p1指向NULL了,不再指向原来的堆空间

    cout << p2->value() << endl;//p2接管了p1所指堆空间

   

    //p2++;不重载++,因为每次只能一个智能指针指向堆空间,这种++操作没意义

   

    //p2智能指针生命期结束,会自动释放接管的堆空间

   

    return 0;

}

运行结果:

//输出结果:

//Test(int i)

//5

//1

//5

//~Test()

 

4. 小结

(1)指针特征操作符( -> 和 * )可以被重载

(2)重载指针特征符能够使用对象代替指针

(3)智能指针只能用于指向堆空间中的内存

(4)智能指针意义在于最大程度避免内存问题

 

posted @ 2018-12-23 23:20  梦心之魂  阅读(383)  评论(0编辑  收藏  举报