在 C++ 应用开发中,STL的算法(algorithm)能够大大降低复杂性和减少代码量。
本文讨论STL的算法用于容器所包含的对象的释放的情况, 这一简单的应用环节。
背景
STL容器类被广泛应用到C++应用中。容器包含的对象的释放的任务不是非常困难的,但是还是有大量的重复性的代码来回复制。在本文中,在容器的类型是类的指针并且是其对象用new来分配的情况下,给出一种简单的设计来管理STL容器包含的对象的释放。
设计的关键所在
首先,设计删除模板类来处理序列式容器,例如 STL vector, deque, list 类.
template<typename TType>class TSeqDeletor
{
public:
void operator () (TType* ptr)
{
if(ptr)
{
delete ptr;
}
}
};
首先,设计删除模板类来处理关联式容器,像 STL map, set.
template<typename TPair>class TAsoDeletor
{
public:
void operator () (TPair& tElem)
{
if(tElem.second)
{
delete tElem.second;
}
}
};
最后,用STL算法来设计函数模板来实现容器所包含的对象的释放:
template<typename TContainer, typename TDelete>class TDealloc
{
public:
void operator()(TContainer& tc)
{
TDelete mdel;
std::for_each<:iterator>(tc.begin(), tc.end(), mdel);
tc.clear();
}
};
TContainer: 容器类.
TDelete: 删除仿函数.
使用设计的例子
下面式例子代码来演示了这个设计的应用:
#include "stdafx.h"
#include "templdefs.h"
#include
#include
#include
using namespace std;
//序列容器的类元素
class CCounter
{
private:
int m_nCounter;
public:
CCounter(int n = 0):m_nCounter(n){};
~CCounter(){printf("Counter %i is released!\n", m_nCounter);}
};
class CAnimal
{
private:
string m_szAnimal;
public:
CAnimal(char* sz):m_szAnimal(sz){};
~CAnimal(){printf("%s is gone!\n", m_szAnimal.c_str());}
};
// 定义具体的序列容器和其删除类
typedef vector CCounterArray;
typedef TSeqDeletor CCounerDel;
typedef TDealloc CCDellocate;
typedef vector CAnimalList;
typedef TSeqDeletor CAnimalDel;
typedef TDealloc CADellocate;
//关联式容器的类元素
class CTextBook
{
private:
string m_szTitle;
public:
CTextBook(char* sz):m_szTitle(sz){};
~CTextBook(){printf("%s is completed!\n", m_szTitle.c_str());}
};
// 定义具体的关联容器和其删除类
typedef map<int, CTextBook*> CBookList;
typedef TAsoDeletor<:value_type> CBookDel;
typedef TDealloc CBDellocate;
typedef pair <int, CTextBook*> book_pair;
int _tmain(int argc, _TCHAR* argv[])
{
int i;
// 演示序列容器所包含对象的释放
CCounterArray cntList;
CAnimalList anList;
char san[20];
// 创建序列容器
for(i = 0; i < 20; i++)
{
CCounter* pct = new CCounter(i);
cntList.push_back(pct);
}
for(i = 0; i < 10; i++)
{
memset(san, 0, 20);
sprintf(san, "Animal%i", i);
CAnimal* pa = new CAnimal(san);
anList.push_back(pa);
}
//释放序列容器包含的对象;
CCDellocate cntFree;
CADellocate anFree;
cntFree(cntList);
anFree(anList);
//演示关联容器所包含对象的释放
CBookList bookList;
char szt[40];
for(i = 0; i < 10; i++)
{
memset(szt, 0, 40);
sprintf(szt, "The Book Title of %i", i);
CTextBook* pb = new CTextBook(szt);
bookList.insert(book_pair(i, pb));
}
//Release the sequence container object;
CBDellocate bookFree;
bookFree(bookList);
return 0;
}
容器对象缓冲的释放是想当容易的,如下:
CCDellocate cntFree;
CADellocate anFree;
cntFree(cntList);
anFree(anList);
CBDellocate bookFree;
bookFree(bookList);
假如我们用普通的方法来释放容器的buffer,代码如下:
CCounterArray::iterator citer;
for(citer = cntList.begin(); citer != cntList.end(); ++citer)
{
if((*citer))
delete (*citer);
}
cntList.clear();
CAnimalList::iterator aiter;
for(aiter = anList.begin(); aiter != anList.end(); ++aiter)
{
if((*aiter))
delete (*aiter);
}
anList.clear();
CBookList::iterator biter;
for(biter = bookList.begin(); biter != bookList.end(); ++biter)
{
if((*biter).second)
delete (*biter).second;
}
bookList.clear();
比较上述两种方式,第一种设计更好地重用了代码,特别是有大量容器对象的情况下,减小了代码,并且设计更符合OOP.
本文仅仅展示了简单的应用情况,但是其思想可以被应用到复杂多变的设计中去。
附件为英文原版文章!