當容器中包含的是通過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泄漏,甚至
// 在上面代碼中拋出異常