浏览量:746

智能指针

示例代码:https://github.com/twinklingstar20/twinklingstar_cn_demo_ogre_smart_pointer

看到Ogre中的智能指针SharedPtr,于是结合以前在Webkit内核中看到的智能指针PassRefPtr和RefPtr一起进行介绍。

由于C++缺乏语言级别的GC(Garbage Collection)支持,实现的代码容易发生内存泄漏的BUG,但是GC也由于额外的负担,降低了代码的效率。另外一种朴素的方法就是智能指针,所谓的智能指针就是将一个计数器与指向的对象的指针相关联,引用计数跟踪该类有多少个对象共享同一指针,当引用计数达到一个阈值时,删除该对象。

对智能指针有深入的理解,前提必须对C++中复制构造函数、运算符重载、对象返回值的原理等有较深入的理解,这些概念的深入理解可以参考《Thinking in C++》这本书中第11章“References &the Copy-Constructor”小节的内容。这里就举一个简单的例子:

#include <iostream>  
#include <vector>  
using namespace std;  
class TestCopyConstructor 
{
public:
	TestCopyConstructor(string nm)
	{
		name = nm;
	}
	TestCopyConstructor& operator=(const TestCopyConstructor& s)//重载运算符 
	{
		this->name = s.name+"New";
		printf("operator = : %s\n",name.c_str());
		return *this;
	}
	TestCopyConstructor(const TestCopyConstructor& s)//复制构造函数 
	{  
		this->name = s.name+"New";
		printf("Copy constructor: %s\n",name.c_str());
	}
public:
	string name;
}; 

int main()  
{
	TestCopyConstructor a("TestA");
	TestCopyConstructor b = a;

	TestCopyConstructor c("TestC");
	TestCopyConstructor d("TestD");
	d = c;

	return 0;  
}

第一次赋值操作b = a,申明时候的初始化,调用的是复制构造函数;第二次赋值操作d = c,调用的是=符号的重载函数。

一般采用C++模板关键字来实现智能指针。计数值count初始化为1;每调用该指针的复制构造、=符号重载、作为构造函数的参数进行值传递等情况,计数值count加1;调用析构函数时,计数值减1;当计数值小于1时,释放该指针的内存。

对智能指针典型的实现有:(1)STL中的auto_ptr;(2)Boost中的scoped_ptr;(3)浏览器内核webkit中的RefPtr、PassRefPtr等;(4)ogre渲染引擎中的SharedPtr。

浏览器内核Webkit内核中,有很多种智能指针的实现,这里以RefPtr和PassRefPtr为例,参考【1】,对Webkit内核中RefPtr和PassRefPtr进行了详细地介绍,【2】是相应的翻译版本,这篇文章对RefPtr和PassRefPtr的原理、实现思想、使用方法都有介绍,这里就不赘述。我的工作是将Webkit内核中RefPtr和PassRefPtr的代码剥离出来,并写了个简单应用的DEMO。这两个类的代码如下面所示,在文章的最后提供了该智能指针的下载。

PassRefPtr.h文件

/*
 *  Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 *
 */

#ifndef WTF_PassRefPtr_h
#define WTF_PassRefPtr_h

template<typename T> class RefPtr;
template<typename T> class PassRefPtr;
template<typename T> PassRefPtr<T> adoptRef(T*);

inline void adopted(const void*) { }

#define ALWAYS_INLINE inline

template<typename T> ALWAYS_INLINE void refIfNotNull(T* ptr)
{
    if (ptr != 0)
        ptr->ref();
}

template<typename T> ALWAYS_INLINE void derefIfNotNull(T* ptr)
{
    if (ptr != 0)
        ptr->deref();
}

template<typename T> 
class PassRefPtr 
{
public:
    PassRefPtr() : m_ptr(0) { }
    PassRefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
    // It somewhat breaks the type system to allow transfer of ownership out of
    // a const PassRefPtr. However, it makes it much easier to work with PassRefPtr
    // temporaries, and we don't have a need to use real const PassRefPtrs anyway.
    PassRefPtr(const PassRefPtr& o) : m_ptr(o.leakRef()) { }
    template<typename U> PassRefPtr(const PassRefPtr<U>& o) : m_ptr(o.leakRef()) { }

    ALWAYS_INLINE ~PassRefPtr() { derefIfNotNull(m_ptr); }

    template<typename U> PassRefPtr(const RefPtr<U>&);

    T* get() const { return m_ptr; }

    T* leakRef() const;

    T& operator*() const { return *m_ptr; }
    T* operator->() const { return m_ptr; }

    bool operator!() const { return !m_ptr; }

    // This conversion operator allows implicit conversion to bool but not to other integer types.
    typedef T* (PassRefPtr::*UnspecifiedBoolType);
    operator UnspecifiedBoolType() const { return m_ptr ? &PassRefPtr::m_ptr : 0; }

    PassRefPtr& operator=(const PassRefPtr&) { return *this; }

    friend PassRefPtr adoptRef<T>(T*);

private:
    // adopting constructor
    PassRefPtr(T* ptr, bool) : m_ptr(ptr) { }

    mutable T* m_ptr;
};

template<typename T> template<typename U> ALWAYS_INLINE PassRefPtr<T>::PassRefPtr(const RefPtr<U>& o)
    : m_ptr(o.get())
{
    T* ptr = m_ptr;
    refIfNotNull(ptr);
}

template<typename T> ALWAYS_INLINE T* PassRefPtr<T>::leakRef() const
{
    T* ptr = m_ptr;
    m_ptr = 0;
    return ptr;
}

template<typename T, typename U> ALWAYS_INLINE bool operator==(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
{ 
    return a.get() == b.get(); 
}

template<typename T, typename U> ALWAYS_INLINE bool operator==(const PassRefPtr<T>& a, const RefPtr<U>& b) 
{ 
    return a.get() == b.get(); 
}

template<typename T, typename U> ALWAYS_INLINE bool operator==(const RefPtr<T>& a, const PassRefPtr<U>& b) 
{ 
    return a.get() == b.get(); 
}

template<typename T, typename U> ALWAYS_INLINE bool operator==(const PassRefPtr<T>& a, U* b) 
{ 
    return a.get() == b; 
}

template<typename T, typename U> ALWAYS_INLINE bool operator==(T* a, const PassRefPtr<U>& b) 
{
    return a == b.get(); 
}

template<typename T, typename U> ALWAYS_INLINE bool operator!=(const PassRefPtr<T>& a, const PassRefPtr<U>& b) 
{ 
    return a.get() != b.get(); 
}

template<typename T, typename U> ALWAYS_INLINE bool operator!=(const PassRefPtr<T>& a, const RefPtr<U>& b) 
{ 
    return a.get() != b.get(); 
}

template<typename T, typename U> ALWAYS_INLINE bool operator!=(const RefPtr<T>& a, const PassRefPtr<U>& b) 
{ 
    return a.get() != b.get(); 
}

template<typename T, typename U> ALWAYS_INLINE bool operator!=(const PassRefPtr<T>& a, U* b)
{
    return a.get() != b; 
}

template<typename T, typename U> ALWAYS_INLINE bool operator!=(T* a, const PassRefPtr<U>& b) 
{ 
    return a != b.get(); 
}

template<typename T> ALWAYS_INLINE PassRefPtr<T> adoptRef(T* p)
{
    adopted(p);
    return PassRefPtr<T>(p, true);
}

template<typename T, typename U> ALWAYS_INLINE PassRefPtr<T> static_pointer_cast(const PassRefPtr<U>& p) 
{ 
    return adoptRef(static_cast<T*>(p.leakRef())); 
}

template<typename T, typename U> inline PassRefPtr<T> const_pointer_cast(const PassRefPtr<U>& p) 
{ 
    return adoptRef(const_cast<T*>(p.leakRef())); 
}

template<typename T> ALWAYS_INLINE T* getPtr(const PassRefPtr<T>& p)
{
    return p.get();
}

#endif // WTF_PassRefPtr_h

RefPtr.h文件

/*
 *  Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Library General Public
 *  License as published by the Free Software Foundation; either
 *  version 2 of the License, or (at your option) any later version.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Library General Public License for more details.
 *
 *  You should have received a copy of the GNU Library General Public License
 *  along with this library; see the file COPYING.LIB.  If not, write to
 *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 *  Boston, MA 02110-1301, USA.
 *
 */

// RefPtr and PassRefPtr are documented at http://webkit.org/coding/RefPtr.html

#ifndef WTF_RefPtr_h
#define WTF_RefPtr_h

#include <algorithm>
#include "PassRefPtr.h"

template<typename T> class PassRefPtr;

template<typename T> 
class RefPtr 
{
public:
    ALWAYS_INLINE RefPtr() : m_ptr(0) { }
    ALWAYS_INLINE RefPtr(T* ptr) : m_ptr(ptr) { refIfNotNull(ptr); }
    ALWAYS_INLINE RefPtr(const RefPtr& o) : m_ptr(o.m_ptr) { refIfNotNull(m_ptr); }
    template<typename U> ALWAYS_INLINE RefPtr(const RefPtr<U>& o) : m_ptr(o.get()) { refIfNotNull(m_ptr); }

    // See comments in PassRefPtr.h for an explanation of why this takes a const reference.
    template<typename U> ALWAYS_INLINE RefPtr(const PassRefPtr<U>&);

    ALWAYS_INLINE ~RefPtr() { derefIfNotNull(m_ptr); }

    ALWAYS_INLINE T* get() const { return m_ptr; }

    ALWAYS_INLINE void clear();
    ALWAYS_INLINE PassRefPtr<T> release() { PassRefPtr<T> tmp = adoptRef(m_ptr); m_ptr = 0; return tmp; }

    ALWAYS_INLINE T& operator*() const { return *m_ptr; }
    ALWAYS_INLINE T* operator->() const { return m_ptr; }

    ALWAYS_INLINE bool operator!() const { return !m_ptr; }

    // This conversion operator allows implicit conversion to bool but not to other integer types.
    typedef T* (RefPtr::*UnspecifiedBoolType);
    ALWAYS_INLINE operator UnspecifiedBoolType() const { return m_ptr ? &RefPtr::m_ptr : 0; }

    ALWAYS_INLINE RefPtr& operator=(const RefPtr&);
    ALWAYS_INLINE RefPtr& operator=(T*);
    ALWAYS_INLINE RefPtr& operator=(const PassRefPtr<T>&);
    template<typename U> ALWAYS_INLINE RefPtr& operator=(const RefPtr<U>&);
    template<typename U> ALWAYS_INLINE RefPtr& operator=(const PassRefPtr<U>&);

    ALWAYS_INLINE void swap(RefPtr&);

private:
	mutable T* m_ptr;
};

template<typename T> template<typename U> inline RefPtr<T>::RefPtr(const PassRefPtr<U>& o)
    : m_ptr(o.leakRef())
{
}

template<typename T> inline void RefPtr<T>::clear()
{
    T* ptr = m_ptr;
    m_ptr = 0;
    derefIfNotNull(ptr);
}

template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<T>& o)
{
    T* optr = o.get();
    refIfNotNull(optr);
    T* ptr = m_ptr;
    m_ptr = optr;
    derefIfNotNull(ptr);
    return *this;
}

template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const RefPtr<U>& o)
{
    T* optr = o.get();
    refIfNotNull(optr);
    T* ptr = m_ptr;
    m_ptr = optr;
    derefIfNotNull(ptr);
    return *this;
}

template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(T* optr)
{
    refIfNotNull(optr);
    T* ptr = m_ptr;
    m_ptr = optr;
    derefIfNotNull(ptr);
    return *this;
}

template<typename T> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<T>& o)
{
    T* ptr = m_ptr;
    m_ptr = o.leakRef();
    derefIfNotNull(ptr);
    return *this;
}

template<typename T> template<typename U> inline RefPtr<T>& RefPtr<T>::operator=(const PassRefPtr<U>& o)
{
    T* ptr = m_ptr;
    m_ptr = o.leakRef();
    derefIfNotNull(ptr);
    return *this;
}

template<class T> inline void RefPtr<T>::swap(RefPtr<T>& o)
{
    std::swap(m_ptr, o.m_ptr);
}

template<class T> inline void swap(RefPtr<T>& a, RefPtr<T>& b)
{
    a.swap(b);
}

template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, const RefPtr<U>& b)
{ 
    return a.get() == b.get(); 
}

template<typename T, typename U> inline bool operator==(const RefPtr<T>& a, U* b)
{ 
    return a.get() == b; 
}

template<typename T, typename U> inline bool operator==(T* a, const RefPtr<U>& b) 
{
    return a == b.get(); 
}

template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, const RefPtr<U>& b)
{ 
    return a.get() != b.get(); 
}

template<typename T, typename U> inline bool operator!=(const RefPtr<T>& a, U* b)
{
    return a.get() != b; 
}

template<typename T, typename U> inline bool operator!=(T* a, const RefPtr<U>& b)
{ 
    return a != b.get(); 
}

template<typename T, typename U> inline RefPtr<T> static_pointer_cast(const RefPtr<U>& p)
{ 
    return RefPtr<T>(static_cast<T*>(p.get())); 
}

template<typename T, typename U> inline RefPtr<T> const_pointer_cast(const RefPtr<U>& p)
{ 
    return RefPtr<T>(const_cast<T*>(p.get())); 
}

template<typename T> inline T* getPtr(const RefPtr<T>& p)
{
    return p.get();
}
#endif // WTF_RefPtr_h

而在Ogre渲染引擎中,提供了智能指针类是SharedPtr,代码如下所示。跟前面的讲的Webkit智能指针主要的区别在于:(1)如果宏定义OGRE_THREAD_SUPPORT是1,即支持多线程,由于互斥量的使用,SharedPtr类可以做到线程安全;(2)SharedPtr在应用上,较PassRefPtr和RefPtr简单,但是可能导致计数值的跳变,计数值跳变的概念在参考【1】中有详细的介绍。

/*
-----------------------------------------------------------------------------
This source file is part of OGRE
    (Object-oriented Graphics Rendering Engine)
For the latest info, see http://www.ogre3d.org/

Copyright (c) 2000-2012 Torus Knot Software Ltd

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-----------------------------------------------------------------------------
*/
#ifndef __SharedPtr_H__
#define __SharedPtr_H__

#include "OgrePrerequisites.h"

namespace Ogre {
	/** \addtogroup Core
	*  @{
	*/
	/** \addtogroup General
	*  @{
	*/

	/// The method to use to free memory on destruction
	enum SharedPtrFreeMethod
	{
		/// Use OGRE_DELETE to free the memory
		SPFM_DELETE,
		/// Use OGRE_DELETE_T to free (only MEMCATEGORY_GENERAL supported)
		SPFM_DELETE_T,
		/// Use OGRE_FREE to free (only MEMCATEGORY_GENERAL supported)
		SPFM_FREE
	};

	/** Reference-counted shared pointer, used for objects where implicit destruction is 
        required. 
    @remarks
        This is a standard shared pointer implementation which uses a reference 
        count to work out when to delete the object. 
	@par
		If OGRE_THREAD_SUPPORT is defined to be 1, use of this class is thread-safe.
    */
	template<class T> class SharedPtr
	{
	protected:
		T* pRep;
		unsigned int* pUseCount;
		SharedPtrFreeMethod useFreeMethod; // if we should use OGRE_FREE instead of OGRE_DELETE
	public:
		OGRE_AUTO_SHARED_MUTEX // public to allow external locking
		/** Constructor, does not initialise the SharedPtr.
			@remarks
				<b>Dangerous!</b> You have to call bind() before using the SharedPtr.
		*/
		SharedPtr() : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
        {
            OGRE_SET_AUTO_SHARED_MUTEX_NULL
        }

		/** Constructor.
		@param rep The pointer to take ownership of
		@param freeMode The mechanism to use to free the pointer
		*/
        template< class Y>
		explicit SharedPtr(Y* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) 
			: pRep(rep)
			, pUseCount(rep ? OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1) : 0)
			, useFreeMethod(inFreeMethod)
		{
            OGRE_SET_AUTO_SHARED_MUTEX_NULL
			if (rep)
			{
				OGRE_NEW_AUTO_SHARED_MUTEX
			}
		}
		SharedPtr(const SharedPtr& r)
            : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
		{
			// lock & copy other mutex pointer

            OGRE_SET_AUTO_SHARED_MUTEX_NULL
            OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
            {
			    OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
			    OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
			    pRep = r.pRep;
			    pUseCount = r.pUseCount; 
				useFreeMethod = r.useFreeMethod;
			    // Handle zero pointer gracefully to manage STL containers
			    if(pUseCount)
			    {
				    ++(*pUseCount); 
			    }
            }
		}
		SharedPtr& operator=(const SharedPtr& r) {
			if (pRep == r.pRep)
				return *this;
			// Swap current data into a local copy
			// this ensures we deal with rhs and this being dependent
			SharedPtr<T> tmp(r);
			swap(tmp);
			return *this;
		}

		template< class Y>
		SharedPtr(const SharedPtr<Y>& r)
            : pRep(0), pUseCount(0), useFreeMethod(SPFM_DELETE)
		{
			// lock & copy other mutex pointer

            OGRE_SET_AUTO_SHARED_MUTEX_NULL
            OGRE_MUTEX_CONDITIONAL(r.OGRE_AUTO_MUTEX_NAME)
            {
			    OGRE_LOCK_MUTEX(*r.OGRE_AUTO_MUTEX_NAME)
			    OGRE_COPY_AUTO_SHARED_MUTEX(r.OGRE_AUTO_MUTEX_NAME)
			    pRep = r.getPointer();
			    pUseCount = r.useCountPointer();
				useFreeMethod = r.freeMethod();
			    // Handle zero pointer gracefully to manage STL containers
			    if(pUseCount)
			    {
				    ++(*pUseCount);
			    }
            }
		}
		template< class Y>
		SharedPtr& operator=(const SharedPtr<Y>& r) {
			if (pRep == r.getPointer())
				return *this;
			// Swap current data into a local copy
			// this ensures we deal with rhs and this being dependent
			SharedPtr<T> tmp(r);
			swap(tmp);
			return *this;
		}
		virtual ~SharedPtr() {
            release();
		}

		inline T& operator*() const { assert(pRep); return *pRep; }
		inline T* operator->() const { assert(pRep); return pRep; }
		inline T* get() const { return pRep; }

		/** Binds rep to the SharedPtr.
			@remarks
				Assumes that the SharedPtr is uninitialised!
		*/
		void bind(T* rep, SharedPtrFreeMethod inFreeMethod = SPFM_DELETE) {
			assert(!pRep && !pUseCount);
            OGRE_NEW_AUTO_SHARED_MUTEX
			OGRE_LOCK_AUTO_SHARED_MUTEX
			pUseCount = OGRE_NEW_T(unsigned int, MEMCATEGORY_GENERAL)(1);
			pRep = rep;
			useFreeMethod = inFreeMethod;
		}

		inline bool unique() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount == 1; }
		inline unsigned int useCount() const { OGRE_LOCK_AUTO_SHARED_MUTEX assert(pUseCount); return *pUseCount; }
		inline unsigned int* useCountPointer() const { return pUseCount; }

		inline T* getPointer() const { return pRep; }
		inline SharedPtrFreeMethod freeMethod() const { return useFreeMethod; }

		inline bool isNull(void) const { return pRep == 0; }

        inline void setNull(void) { 
			if (pRep)
			{
				// can't scope lock mutex before release in case deleted
				release();
				pRep = 0;
				pUseCount = 0;
			}
        }

    protected:

        inline void release(void)
        {
			bool destroyThis = false;

            /* If the mutex is not initialized to a non-zero value, then
               neither is pUseCount nor pRep.
             */

            OGRE_MUTEX_CONDITIONAL(OGRE_AUTO_MUTEX_NAME)
			{
				// lock own mutex in limited scope (must unlock before destroy)
				OGRE_LOCK_AUTO_SHARED_MUTEX
				if (pUseCount)
				{
					if (--(*pUseCount) == 0) 
					{
						destroyThis = true;
	                }
				}
            }
			if (destroyThis)
				destroy();

            OGRE_SET_AUTO_SHARED_MUTEX_NULL
        }

        virtual void destroy(void)
        {
            // IF YOU GET A CRASH HERE, YOU FORGOT TO FREE UP POINTERS
            // BEFORE SHUTTING OGRE DOWN
            // Use setNull() before shutdown or make sure your pointer goes
            // out of scope before OGRE shuts down to avoid this.
			switch(useFreeMethod)
			{
			case SPFM_DELETE:
				OGRE_DELETE pRep;
				break;
			case SPFM_DELETE_T:
				OGRE_DELETE_T(pRep, T, MEMCATEGORY_GENERAL);
				break;
			case SPFM_FREE:
				OGRE_FREE(pRep, MEMCATEGORY_GENERAL);
				break;
			};
			// use OGRE_FREE instead of OGRE_DELETE_T since 'unsigned int' isn't a destructor
			// we only used OGRE_NEW_T to be able to use constructor
            OGRE_FREE(pUseCount, MEMCATEGORY_GENERAL);
			OGRE_DELETE_AUTO_SHARED_MUTEX
        }

		virtual void swap(SharedPtr<T> &other) 
		{
			std::swap(pRep, other.pRep);
			std::swap(pUseCount, other.pUseCount);
			std::swap(useFreeMethod, other.useFreeMethod);
#if OGRE_THREAD_SUPPORT
			std::swap(OGRE_AUTO_MUTEX_NAME, other.OGRE_AUTO_MUTEX_NAME);
#endif
		}
	};

	template<class T, class U> inline bool operator==(SharedPtr<T> const& a, SharedPtr<U> const& b)
	{
		return a.get() == b.get();
	}

	template<class T, class U> inline bool operator!=(SharedPtr<T> const& a, SharedPtr<U> const& b)
	{
		return a.get() != b.get();
	}

	template<class T, class U> inline bool operator<(SharedPtr<T> const& a, SharedPtr<U> const& b)
	{
		return std::less<const void*>()(a.get(), b.get());
	}
	/** @} */
	/** @} */
}

#endif

由于智能指针有额外的开销,所以如果能够明确对象内存的申请和释放的情况,不需要使用智能指针。

开源代码中对智能指针的代码实现都非常的漂亮,可以结合【1】中的文章阅读PassRefPtr.h和RefPtr.h中的代码,说多了都是泪。

参考

【1】       http://www.webkit.org/coding/RefPtr.html

【2】       http://blog.chinaunix.net/uid-7448773-id-603837.html

spacer

Leave a reply