c++ 内存管理
这里介绍几种重用的内存管理方法。
引用计数
这也是最常用的一种内存管理方式,例如OSG、OpenInventer等等。
网上面管理这方面的例子有很多,这里就不再讲解。
重载new/delete的一种方法
这种方法是基于malloc/free方法来管理内存。
优点在于
CHeapOperators类分配的内存地址存储在一个Vector中,程序结束可以保证内存释放。
malloc/free方法不会自动调用类的析构函数,这样管理内存更加清晰。
适合小型项目的加载使用。
#include <new> #undef new #undef delete class CHeapOperators { public: static void* operator new( size_t size ); static void operator delete( void * ptr );
//这里可以添加其他的静态方法
//例如 static void* operator new[]( size_t size ); //申请数组
};
#include <malloc.h> #include <vector> #include <algorithm> std::vector<void *> heapV; //可以使用List等其他容器,目的是记录内存指针 void* CHeapOperators::operator new( size_t size ){ void *ptr = malloc(size); heapV.push_back(ptr); return ptr; } void CHeapOperators::operator delete( void * ptr ){ std::vector<void*>::iterator iterTemp = std::find(heapV.begin(), heapV.end(), ptr); if (iterTemp != heapV.end()) { heapV.erase(iterTemp); } free(ptr); }
//测试类
class CMemTest : public CHeapOperators
{
public:
CMemTest(){
pVal = new double; //这里会调用基类的new 来分配内存。
}
~CMemTest(){
delete (pVal); //这里可以选择注释或者不注释。注释的化在程序结束时一次性清空内存。
}
private:
double *pVal;
};
智能指针
智能指针有什么中,这里只是介绍其中的几种。
指针1
下面介绍的智能指针实际上就是一个重载了操作符 -> 的类。智能接口指针类包含指向另外一个对象的指针。当用户调用智能指针上的 -> 操作符时,
智能指针把此调用转发给它所包含的指针所指的对象。
class CTemp //临时类 { public: virtual void Get(); }; class AutoPter { public: AutoPter(CTemp *p) { m_p = p; } ~AutoPter( ) { if ( m_p != NULL ) delete m_p; } CTemp *operator ->() { return m_p; } private: CTemp *m_p; }; //使用方法,一个例子 void Fun(CTemp *p) { AutoPter t( p ); //创建并初始化智能指针 t->Get(); //在函数执行完后,会调用AutoPter析构函数 }
上述的智慧指针最妙之处可能在于我们无需记住去调用delete。函数执行完毕后,会自动调用析构函数。
当然这只是一个简单的例子,可根据不同的需要对其进行适当修改。
指针2
下面介绍的智能指针,是基于引用计数机制上编写的。 这里同OSG中的 ref_ptr 类似。
代码是摘自COM中的。
template <class T> class CComPtrBase { protected: CComPtrBase() throw() { p = NULL; } CComPtrBase(_Inout_opt_ T* lp) throw() { p = lp; if (p != NULL) p->AddRef(); } public: typedef T _PtrClass; ~CComPtrBase() throw() { if (p) p->Release(); } // Release the interface and set to NULL void Release() throw() { T* pTemp = p; if (pTemp) { p = NULL; pTemp->Release(); } } }