STL push_back new出来的空间如何释放

发布时间 2023-05-04 10:48:22作者: hermione1985

STL中的容器相当“聪明”,它们提供了迭代器,以便进行向后和向前的遍历(通过begin、end、rbegin等);它们告诉你所包含的元素类型(通过它们的value_type类型定义);在插入和删除的过程中,它们自己进行必要的内存管理;它们报告自己有多少对象,最多能容纳多少对象(分别通过size和max_size);当然,当它们自身被析构时,它们自动析构所包含的每个对象。

有了这么“聪明”的容器,许多程序员不再考虑自己做善后清理工作。更糟糕的是,他们认为,容器会考虑为他们做这些事情。很多情况下,他们是对的。但当容器包含的是new的方式而分配的指针时,他们这么想就不正确了。没错,指针容器在自己被析构时会析构所包含的每个元素,但指针的“析构函数”不做任何事情!它当然也不会调用delete。

结果,下面的代码直接导致资源泄露:


void doSomething()
{
vector<Widget*>vwp;
for (int I = 0; I < SOME_MAGIC_NUMBER; ++i)
{
Vwp.push_back(new Widget);

} //在这里发生了Widget资源泄露
}

当vwp的作用域结束时,它的元素全部被析构,但并没有改变通过new创建的对象没有被删除这一事实。删除这些对象是你的责任,不是vector的责任。这是vector的特性。只有你才知道这些指针是否应该被释放。


void doSomething()
{
for (vector<Widget*>::iterator I = vwp.begin(); i != vwp.end(); ++i)
delete *i;
}

 

这样做能行,但只是在你对“能行“不那么挑剔时。一个问题是,新的for循环做的事情和for_each相同,但不如使用for_each看起来那么清楚。问题是,这段代码不是异常安全的。如果在想vwp中填充指针和从中删除指针的两个过程中间有异常抛出的话,同样会有资源泄露。

其一解决方法如下:


struct DeleteObject
{
template<typename T>
void operator() (const T* ptr) const
{
delete ptr;
}
};
void doSomething()
{
deque<SpecialString*> dssp;
for_each (dssp.begin(), dssp.end(), DeleteObject());
}

但它仍然不是异常安全的。如果在SpecialString已经被创建而对for_each的调用还没开始时就有异常被抛出,则会有资源泄露发生。

 

其二解决方法:

利用Boost库中的shared_ptr。


void doSomething()
{
typedef boost::shared_ptr<Widget> SPW; //SPW= “指向Widget的shared_ptr”
vector<SPW> vwp;
for (int I = 0; I < SOME_MAGIC_NUMBER; ++i)
vwp.push_back(SPW(new Widget));

} //这里不会有Widget泄露,即使在上面的代码中有异常被抛出

永远不要错误的认为:你可以通过创建auto_ptr的容器使指针被自动删除。这个想法很危险,具体解释请看Effective STL 第8条。

 

你要记住的是:STL容器很智能,但没有智能到知道是否该删除自己所包含的指针的程度。当你使用指针的容器,而其中的指针应该被删除时,为了避免资源泄露,你必须或者用引用计数形式的智能指针对象(比如Boost的shared_ptr)代替指针,或者容器被析构时手工删除其中的每个指针。

原文链接:https://blog.csdn.net/u012432778/article/details/42065759