1、智能指针本质上是一个对象,这个对象可以像原生的一样来进行使用。原因是智能指针对象对应的类中,将指针相关的操作都进行了重载操作处理,所以才会达到这种像是原生的效果。


2、智能指针的意义:

现在C++开发库中最重要的类模板之一

C++中自动内存管理的主要手段

能够在很大程度上避开内存相关的问题


3、在QT中开发库中也提供了智能指针类模板,在STL标准库中也提供了,在c++的标准库忘了什么名了中也提供了智能指针类模板。所以智能指针类模板在C++中的地位很重要


4、STL中的智能指针类模板 auto_ptr,在memory这个头文件中。


(1)生命周期结束时,销毁指向的内存空间


(2)不能指向堆数组,只能指向堆对象(变量)


(3)一片堆空间只属于一个智能指针对象


(4)多个智能指针对象不能指向同一片堆空间


既然auto_ptr是一个类模板,所以使用时就要指定类型参数。如a:auto_ptr<Test> pt(new Test()); pt.get();可以返回pt所指向的空间的内存起始地址.


5、STL中的其他智能指针 


(1)shared_ptr:带有引用计数机制,所以可以支持多个指针对象指向同一片内存空间


(2)weak_ptr:配合shared_ptr而引人的一种智能指针


(3)unique_ptr:一个指针对象只能指向一片内存空间,但是不能进行所有权的转移,所以就不能拷贝构造和赋值。



例:STL标准库中auto_ptr的使用


#include <iostream>

#include <string>

#include <memory> //auto_ptr这个智能指针类模板就在这个头文件中


using namespace std;


/*

* STL标准库中的auto_ptr智能指针类模板的使用。

* auto_ptr的特点:

* 生命周期结束时,销毁指向的内存空间

* 不能指向堆数组,只能指向堆对象(变量)

* 一片堆空间只属于一个智能指针对象

* 多个智能指针对象不能指向同一片堆空间

*/



class Test

{

private:

string m_name;

public:

Test(const char *name)

{

m_name = name;

cout << "Hello." << "I'm " << name << endl; 

}

void print()

{

cout << "why_fangqingqing " << endl;

}

~Test()

{

cout << "Goodbye " << m_name << endl;

}

};


int main(void)

{

auto_ptr<Test> pt1(new Test("why"));

cout << "pt1 = " << pt1.get() << endl; //获取指向的内存空间的起始地址

pt1->print();

auto_ptr<Test> pt2(pt1); //pt2指向了pt1指向的内存空间,pt1释放掉指向的内存空间,这是auto_ptr的特点,一片内存空间只能由一个auto_ptr指针对象指向

cout << "pt1 = " << pt1.get() << endl; // 0

cout << "pt2 = " << pt2.get() << endl;

pt2->print();

return 0;

}



6、Qt中的智能指针类模板


(1)QPointer,在Qt中包含QPointer头文件就可以使用这个QPointer智能指针类模板了


@1:当其指向的对象被销毁时,它会被自动置空。(也就是说可以多个QPointer智能指针指向同一个对象,当这个对象被销毁的时候,所有的指向这个对象的QPointer指针都变为空了)


@2:析构时不会自动销毁所指向的对象。(也就是说QPoniter指针生命周期结束的时候,不会自动删除所指向的对象(堆空间),我们要手动的delete掉,手动delete一次之后,所有指向这个堆

空间的QPointer指针都会被置为空)


(2)QSharedPointer,在Qt中的QSharedPointer头文件中。


@1:引用计数型智能指针


@2:可以被自由的拷贝和赋值


@3:当引用计数为0时才删除指向的对象(也就是,当这个对象被一次QSharedPointer指针指向时,就会加一次这个对象的引用的次数。当指向这个对象的QSharedPointer指针少一个时,

就会减一次这个对象的引用次数,直到减到没有一个QSharedPointer指针指向这个对象时,也就是这个对象被QSharedPointer指针引用次数为0时,才会销毁这个对象)


在Qt开发中,所有自己写的类,都要去继承QObject这个顶层父类,也就是基类。


7、Qt中的其他智能指针类模板


(1)QWeakPointer


(2)QScopedPointer


(3)QSharedDataPointer


(4)QExplicitlySharedDataPointer



例:


#include <QPointer>

#include <QSharedPointer>

#include <QString>

#include <QDebug>


/*

* Qt开发库中的QPointer智能指针和QSharedPo智能指针类模板的使用。

* QPointer的特点:

* @1:当其指向的对象被销毁时,它会被自动置空。

*  (也就是说可以多个QPointer智能指针指向同一个对象,当这个对象被销毁的时候,所有的指向这个对象的QPointer指针都变为空了)

* @2:析构时不会自动销毁所指向的对象。(也就是说QPoniter指针生命周期结束的时候,

* 不会自动删除所指向的对象(堆空间),我们要手动的delete掉,手动delete一次之后,所有指向这个堆空间的QPointer指针都会被置为空)

*/


/*

*   QSharedPointer的特点:

*   @1:引用计数型智能指针

*   @2:可以被自由的拷贝和赋值

*   @3:当引用计数为0时才删除指向的对象(也就是,当这个对象被一次QSharedPointer指针指向时,就会加一次这个

*   对象的引用的次数。当指向这个对象的QSharedPointer指针少一个时,就会减一次这个对象的引用次数,

*   直到减到没有一个QSharedPointer指针指向这个对象时,也就是这个对象被QSharedPointer指针引用次数为0时,才会销毁这个对象)

*/


class Test : public QObject //Qt中所有自己完成的类都要继承这个Qt中的QObject顶层父类,基类

{

private:

    QString m_name;

public:

    Test(const char *name)

    {

        m_name = name;


        qDebug() << "Hello." << "I'm " << name;

    }


    void print()

    {

        qDebug() << "why_fangqingqing ";

    }


    ~Test()

    {

        qDebug() << "Goodbye " << m_name;

    }

};


int main(void)

{

    QPointer<Test> pt1(new Test("why"));

    QPointer<Test> pt2(pt1);


    qDebug() << "pt1 = " << pt1;

    qDebug() << "pt2 = " << pt2;


    pt1->print();

    pt2->print();


    delete pt1; //要手动的去delete掉pt1所指向的堆空间。编译器不会自动的去销毁,当生命周期结束时,delete掉后,所有指向这个空间

                //的QPointer指针都会被置为空。

    qDebug() << "pt1 = " << pt1;    //0

    qDebug() << "pt2 = " << pt2;    //0


    qDebug() << endl;


    QSharedPointer<Test> spt1(new Test("fangqingqing"));    //这时这个堆空间的对象被QSharedPoin引用了一次

    QSharedPointer<Test> spt2(spt1);    //这时这个堆空间的对象被QSharedPoin引用又加了一次


    qDebug() << "spt1 = " << spt1;

    qDebug() << "spt2 = " << spt2;


    spt1->print();

    spt2->print();


    return 0;       //当那个堆空间的对象被QSharedPointer引用的次数减到0时,就会销毁这个堆空间的对象

}




7、自己实现一个智能指针类模板



#ifndef _SMARTPOINTER_H_

#define _SMARTPOINTER_H_


template

< typename T >

class Pointer

{

private:

T *mp;

public:

Pointer(T* p = NULL)

{

mp = p;

}

Pointer(const Pointer<T>& obj)

{

mp = obj.mp;

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

}

Pointer<T>& operator = (const Pointer<T>& obj)

{

if (this != &obj)

{

delete mp;

mp = obj.mp;

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

}

return *this;

}

T* get()

{

return mp;

}

T* operator -> ()

{

return mp;

}

T& operator * ()

{

return *mp;

}

~Pointer()

{

delete mp;

}

bool isNULL()

{

return (mp == NULL);

}

};



#endif