C++中的智能指针
众所周知。C++中对堆内存的申请与释放全然由用户来控制,这就造成用户在使用的时候常常造成内存泄漏、野指针、反复释放等常见的挂掉问题,所以我们有必要提供一套机制。使得用户仅仅需申请对应的内存,不用管释放的问题,事实上这属于著名的RAII(Resource Acquisition Is Initialization)技术 。在C++中这样的技术称作“智能指针”,C++中的智能指针技术越来越受到广泛应用。以下简要介绍下智能指针。
从以上描写叙述中能够看出,我们须要提供一套内存显式申请与隐式释放,并向用户屏蔽这些细节的机制,对于这样的隐藏细节的做法。我们一般会用一个句柄类来封装。
在这里句柄类就是我们提供给用户的智能指针类。
智能指针为何“智能”呢?这里就涉及到还有一项重要技术”引用计数“。当有N个智能指针句柄类指向同一段内存,这时就会将这段内存的引用计数设置为N,每当当中的一个句柄离开作用域时会自己主动调用析构函数。将内存引用计数减一,这样当某个智能指针句柄类的引用计数为1时,表示这段内存仅仅有该句柄指向它。
在这个过程中。析构函数起非常大的作用,RAII技术也是基于析构函数而实现的。
说了这么多,直接看代码:
/* * refcount.h 引用计数 * lming_08@hotmail.com */ #ifndef _REFCOUNT_H_ #define _REFCOUNT_H_ class RefCount { public: RefCount() : use(new size_t(1)){} RefCount(const RefCount &refcnt) : use(refcnt.use) { inc(); } ~RefCount() { if (decr() == 0) { delete use; } } RefCount & operator=(const RefCount &refcnt) { if (decr() == 0) { delete use; } use = refcnt.use; inc(); return *this; } void init() { use = new size_t(1); } bool only() { return *use == 1; } inline size_t inc() { return ++*use; } inline size_t decr() { return --*use; } bool reattach(const RefCount &refcnt) { ++*refcnt.use; if (only()) { delete use; use = refcnt.use; return true; } else { --*use; use = refcnt.use; return false; } } private: size_t *use; }; #endif // _REFCOUNT_H_
/* * smartpointer.h 智能指针 * lming_08@hotmail.com */ #ifndef _SMARTPOINTER_H_ #define _SMARTPOINTER_H_ #include "refcount.h" template <typename T> class SmartPtr { public: SmartPtr() : ptr_(new T) { refcnt_.init(); } SmartPtr(const T & obj) : ptr_(new T(obj)){} SmartPtr(T * pobj) : ptr_(pobj) { //refcnt_初始化时,*use = 1 if (pobj == nullptr) { refcnt_.decr(); } } SmartPtr(const SmartPtr &spnt) : ptr_(spnt.ptr_), refcnt_(spnt.refcnt_){ } ~SmartPtr() { if (refcnt_.only()) { delete ptr_; ptr_ = nullptr; } } SmartPtr & operator=(const SmartPtr &spnt) { //这一步相当于对refcnt_进行赋值 if (refcnt_.reattach(spnt.refcnt_)) { delete ptr_; } ptr_ = spnt.ptr_; return *this; } T * operator->() { return ptr_; } private: T * ptr_; RefCount refcnt_; }; #endif // _SMARTPOINTER_H_
/* * main.cpp 測试程序 * lming_08@hotmail.com */ #include "memleakcheck.h" #include "smartpointer.h" #include <iostream> #include <string> #include <boost/shared_ptr.hpp> int main(void) { { SmartPtr<int> sp(2); SmartPtr<int> sp2(sp); SmartPtr<int> sp3(3); sp = sp3; sp2 = sp3; } { SmartPtr<std::string> sp("123"); SmartPtr<std::string> sp2(sp); SmartPtr<std::string> sp3("abc"); sp = sp3; sp2 = sp3; } { SmartPtr<std::string> sp(new std::string("123")); SmartPtr<std::string> sp2(sp); SmartPtr<std::string> sp3(new std::string("abc")); sp = sp3; sp2 = sp3; } { boost::shared_ptr<char> pch(new char[10]); } _CrtDumpMemoryLeaks(); return 0; }
memleakcheck.h文件主要用作VS平台内存泄漏检測工具,代码參考于http://blog.csdn.net/windows_nt/article/details/8652191
调试时,发现输出窗体并没有检測到内存泄漏。说明智能指针实现正确。main.cpp中还測试了Boost库中智能指针的使用,能够看到也是非常方便的,眼下在开源点云库PCL中随处都可见到Boost库中的智能指针。
以上代码见github:https://github.com/lming08/Ruminations/
參考资料:
http://www.cnblogs.com/zhangyunkui/archive/2009/11/13/1602514.html