C++智能指针的设计和使用

admin 10年前

对于一个C++的使用者来说,指针的使用可以算的上是家常便饭,但是在使用的过程中,很多时候可能会因为new或者malloc了一个对象,而忘记最后结束的时候去释放掉(我就会犯这样子的错误),从而导致内存泄露。而此时智能指针可能可以帮助我去解决这个问题。

智能指针(smart pointer)是利用个引用计数的策略去处理指针的释放,从而保证指针的安全性。通常情况下,我们会自己去设计一个智能指针类去管理自己的指针对象。其 实其原理是存储指向动态分配的指针对象类,通过引用计数的功能去控制,去正确的实现指针对象的销毁,从而避免内存泄露。

智能指针的原理是,通过将指针类和一个引用计数关联起来,而引用计数 计算,当前指针被多少个对象所共享。 每次创建一个新的指针对象的时候,初始化指针并将引用计数置为1;当对象作为另一个对象的副本而被创建的时候,拷贝构造函数拷贝指针并增加与之对应的引用 计数。对于一个对象进行赋值时,赋值操作符减少左操作数所指对象的引用计数(如果引用计数为减至0,则删除对象),并且增加右操作数所指对象的引用计数; 调用析构函数时,构造函数减少引用计数(如果引用计数减至0,删除基础对象)。

下面的代码主要是借鉴了百度百科的代码来学习智能指针:

    #include<iostream>        #include<stdexcept>        using namespace std;        #define TEST_SMARTPTR        class Stub        {        public:            void print(){                cout<<"Stub:print"<<endl;            }            ~Stub(){                cout<<"Stub:Destructor"<<endl;            }        };        template<typename T>        class SmartPtr        {        public:            SmartPtr(T*p=0):ptr(p),pUse(new size_t(1)){}            SmartPtr(const SmartPtr& src):ptr(src.ptr),pUse(src.pUse){                ++*pUse;            }            SmartPtr&operator=(const SmartPtr& rhs){                //self-assigningisalsoright                ++*rhs.pUse;                decrUse();                ptr=rhs.ptr;                pUse=rhs.pUse;                return *this;            }            T* operator->(){                if(ptr)                    return ptr;                throw std::runtime_error("accessthroughNULLpointer");            }            const T* operator->()const{                if(ptr)                    return ptr;                throw std::runtime_error("accessthroughNULLpointer");            }            T &operator*(){                if(ptr)                    return *ptr;                throw std::runtime_error("dereferenceofNULLpointer");            }            const T &operator*()const{                if(ptr)                    return *ptr;                throw std::runtime_error("dereferenceofNULLpointer");            }            ~SmartPtr(){                decrUse();        #ifdef TEST_SMARTPTR                std::cout<<"SmartPtr:Destructor"<<std::endl;//fortesting        #endif            }        private:            void decrUse(){                if(--*pUse==0){                    delete ptr;                    delete pUse;                }            }            T* ptr;            size_t* pUse;        };        int main()        {            try{                SmartPtr<Stub> t;                t->print();            }catch(const exception&err){                cout<<err.what()<<endl;            }            SmartPtr<Stub>t1(new Stub);            SmartPtr<Stub>t2(t1);            SmartPtr<Stub>t3(new Stub);            t3=t2;            t1->print();            (*t3).print();            return 0;        }  
在面的代码中,智能指针一般都会去重载->和*操作符,从而使其表现指针的表象,并且大家可以使用它像使用指针一样。

在函数析构的时候,我们会发现引用计数在其中所起到的作用,从而避免误操作早成指针提前释放,造成指针悬挂,或者释放不彻底,造成内存泄漏的问题。

来自:http://blog.csdn.net/haitunxiaomo/article/details/42042345