1.2 重载操作符new/delete实现内存监控
由于C++使用new/delete来分配/释放内存,所以可以通过重载new/delete来监控本模块的内存使用情况,比如检测内存泄漏。
//Define a big enough global table.
void *operator new(size_t size)
{
void *p = malloc(size);
record p in the global table; //If multithreads, mutex needed
return p;
}
void operator delete(void *p)
{
remove the record from global table; //If multithreads, mutex needed
free(p);
}
|
程序可以定期打印出global table内容以查看有无泄漏。
1.3 智能指针(Smart Pointer)
智能指针是对原始指针(Raw Pointer)的智能管理,它对原始指针进行引用计数,对指针的拷贝、销毁进行监控,只有在引用计数为0时才真正删除,同时还可以预防空指针的访问。智能指针提高了指针使用的安全性,而且还可以在一定程度上像Java一样做到内存回收,避免了内存泄漏。
SmartPtr.h
class Target;
/** This class represents a smart pointer to Target. */
class SmartPtr
{
public:
/** Default constructor */
SmartPtr();
/** Copy Constructor */
SmartPtr( const SmartPtr& tg);
/** Construct smart pointer from a new target */
SmartPtr(Target* target);
/** Destructor */
~SmartPtr();
// Assignment operator
SmartPtr& operator=(const SmartPtr& p);
// Assignment operator
SmartPtr& operator=(Target* p);
/** Returns true if the smart pointer has not been initialized with
* a target.
*/
bool isNil();
/** Make the smart pointer uninitialized (i.e., the smart pointer is no longer pointing
* to any target object.
*/
void nil();
Target* operator->() const;
private:
// Pointer to actual object
Target* m_tgtPtr;
};
|
SmartPtr.cpp
#include "/Target.h"
#include "SmartPtr.h"
SmartPtr::SmartPtr()
{
// This initializes the object pointer to null.
m_tgtPtr = (Target *)0L;
}
SmartPtr::SmartPtr(const SmartPtr& dp )
{
m_tgtPtr = (Target *)0L;
/* This next statement uses the overloaded operator=(SmartPtr&) defined below
* to decrement the reference count for the
* old Target object used by this class and increment the
* usage count for the new Target object.
*/
*this = dp;
}
SmartPtr::SmartPtr( Target *dp )
{
m_tgtPtr = (Target *)0L;
/* This next statement uses the overloaded operator=(Target *) defined below
* to decrement the reference count for the
* old Target object used by this class and increment the
* usage count for the new Target object.
*/
*this = dp;
}
SmartPtr::~SmartPtr()
{
// This will cause a decrement of the Target reference count
// via the operator=(Target *) defined below
*this = (Target *) 0L;
}
SmartPtr& SmartPtr::operator= (const SmartPtr& newPtr)
{
// This has the effect of calling the overloaded operator=(Target *)
// method which adjusts the Target reference count
*this = newPtr.m_tgtPtr;
return *this;
}
bool SmartPtr::isNil()
{
return( ( dPtr == 0L ) );
}
void SmartPtr::nil()
{
// This will cause a decrement of the Target reference count
// via the operator=(Target *) defined below
*this = 0L;
}
// This overloading will allow the user of this handle to access public
// methods and data members of Target, as though they were members of SmartPtr.
// For example, where you might do a req->setX() you can do a reqPtr->setX() with the same
// effect
Target *SmartPtr::operator-> () const
{
return(m_tgtPtr);
}
SmartPtr& SmartPtr::operator= (Target *newTgt)
{
/* This method is the main method keeping track of the
* reference count for the associated Target object.
*/
// If the pointer passed is not null then bump up the reference
// count for the source Target.
if(newTgt != 0L )
{
newTgt->incrRefCount();
}
// If the pointer this object is currently using is not null
// then decrement the count for that pointer.
if(m_tgtPtr != 0L ) {
// If the count has reached zero, then it is time to delete this
// object
if(m_tgtPtr->decrRefCount() == 0 )
{
delete m_tgtPtr;
}
}
// Have this smart pointer now point to the new Target object.
m_tgtPtr = newTgt;
return(*this);
}
|
Target.h
#include “SmartPtr.h”
class Target
{
public:
Target()
{
m_refCount = 0;
}
virtual ~Target();
void DoSth();
protected:
friend class SmartPtr;
int incrRefCount()
{
return ++m_refCount; //Mutex protection needed for multi-threads
}
int decrRefCount()
{
if(--m_refCount < 0) //Mutex protection needed for multi-threads
m_refCount = 0;
return m_refCount;
}
int m_refCount;
//Add mutex for multi-threads
};
Target::~Target()
{
m_refCount = 0;
}
|
使用示例
void Foo()
{
Target *p = new Target();
SmartPtr sp(p);
SmartPtr sp2 = p; //p’s reference count is 2
sp->DoSth();
sp2->DoSth(); // p will be destroyed automatically after function returns
}
|
任何需要做成智能指针的对象,都可以从Target派生。
1.4 STL
模板是一种泛型编程概念。通过使用模板可以使程序具有更好的代码重用性。模板是对源代码进行重用,而不是通过继承和组合重用对象代码,当用户使用模板时,参数由编译器来替换。
泛型编程和面向对象编程不同,它并不要求你通过额外的间接层来调用函数,它让你编写完全一般化并可重复使用的算法,其效率与针对某特定数据类型而设计的算法相同。所谓泛型(Generic),是指具有在多种数据类型上皆可操作的含意。
STL(Standard Template Library,标准模板库) 是泛型编程的一个代表作品。STL是一个容器(Container)的集合(比如list、vector等),它的主要概念是Containter和Iterator。它使用很方便,而且效率很高。
严格而言,STL并不是面向对象的概念,它属于C++的一个特色(现在Java6中也引入了STL)。