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