当容器中包含的是通过new的方式分配的指针时,指针容器在自己被析构时会析构所包含的所有元素,但指针的“析构函数”不做任何事情!它当然也不会调用delete
1.可用于for_each的伪函数
template<typename T>
struct DeleteObject : // 条款40描述了为什么
public unary_function<const T*, void> { // 这里有这个继承
void operator()(const T* ptr) const
{
delete ptr;
}
};
for_each(vwp.begin(), vwp.end(), DeleteObject<Widget>);
2.从没有析构函数的类公有继承是c++大忌
3.你可以通过编译器推断传给DeleteObject::operator()的指针的类型来消除这个错误(也减少DeleteObject的用户
需要的击键次数)。我们需要做的所有的事就是把模板化从DeleteObject移到它的operator():
struct DeleteObject { // 删除这里的
// 模板化和基类
template<typename T> // 模板化加在这里
void operator()(const T* ptr) const
{
delete ptr;
}
}
编译器知道传给DeleteObject::operator()的指针的类型,所以我们可以让它通过指针的类型自动实例化一个
operator()。这种类型演绎下降让我们放弃使DeleteObject可适配的能力(参见条款40)。
for_each(dssp.begin(), dssp.end(),DeleteObject ());
4.对于第3中方式
直截了当而且类型安全,正如我们喜欢的一样。
但仍不是异常安全的。如果在SpecialString被new但在调用for_each之前抛出一个异常,就会发生泄漏。
void doSomething()
{
typedef boost::shared_ ptr<Widget> SPW; //SPW = "shared_ptr
// to Widget"
vector<SPW> vwp;
for (int i = 0; i < SOME_MAGIC_NUMBER; ++i)
vwp.push_back(SPW(new Widget)); // 从一个Widget建立SPW,
// 然后进行一次push_back
... // 使用vwp
} // 这里没有Widget泄漏,甚至
// 在上面代码中抛出异常