4

为什么我需要手动删除向量中动态创建的项目?当向量被删除时,为什么它们不会被删除或调用其析构函数?

通常是这样的,但为什么需要?

vector<int*> v;
for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it) 
{ 
   delete *it; 
}
4

4 回答 4

12

首先,您将原始指针存储在向量中。这些指针只是指针。他们可以指向任何地方。它们可以指向本地对象,这些对象不能被delete. 即使它们指向动态创建的对象,也不一定意味着用户希望它们与向量一起死亡。向量应该如何知道这一切?

这是对象所有权的问题。拥有该对象的人应对其正确及时的删除负责。普通的原始指针不表示所有权。这就是为什么vector无法对对象是否需要删除做出任何假设。如果您想告诉向量它拥有其动态对象,请使用相应的智能指针。

其次,请注意,您的删除技术在一般情况下不一定安全。一些标准容器假定您存储在其中的数据始终有效。当您delete对每个向量元素执行此操作时,向量中的数据将变为“无效”(指针变得不确定)。这对向量来说是可以的。但是在一个“更智能”的容器中做这样的事情,比如std::mapstd::unordered_set例如,可能而且将会导致问题。即使您随后立即销毁容器本身,容器的销毁算法也很可能需要分析(比较、散列等)各个元素的值。而你只是用你的周期杀死了他们。

智能指针自然地解决了这个问题。但是,如果您必须使用delete存储在标准容器中的原始指针的手册,则更好的步骤顺序将是

  1. 检索元素的值i并将其存储在指针中p
  2. i从容器中擦除元素
  3. delete p

最后你会得到一个空容器和deleted 数据。同样,您的方法适用于简单的序列,例如std::vectoror std::list,但不要对有序或散列的序列执行此操作。

于 2012-08-05T00:58:21.293 回答
6

因为语言无法知道您完成后是否需要它们保持活力。如果您插入一些指向堆栈对象的指针或类似的东西怎么办?繁荣。

然而,这可以通过使用智能指针来解决,智能指针实施适当的策略来自动销毁。unique_ptr并且shared_ptr是最常见和最有用的。

于 2012-08-05T00:49:49.327 回答
3

不调用析构函数是因为指针不拥有它所指向的对象。

在 C++11 中,astd::unique_ptr<T>确实拥有它所指向的对象。在这种情况下,释放指针时会调用析构函数,这可能是您想要的行为。(如果您没有 C++11 编译器,但拥有相当新的 C++11 之前的编译器,unique_ptr则仍可作为 TR1 的一部分使用。)

于 2012-08-05T00:48:26.800 回答
1

的实现vector只是为了删除它的内存。指针没有解构器。而在 C++ 中,没有垃圾收集或逻辑可以看到它是指针并递归删除它。

如果你想参加下一次 ISO 会议并提出这个建议,请做我的客人,但对我来说,我只是把它放在一个inline函数中:

template<class T>
public static inline void deleteVectorPointer(std::vector<T*> v)
{
    for (vector<T*>::iterator i = v.begin(); i != v.end(); i++)
    {
        delete *i;
    }
}
于 2012-08-05T00:35:53.737 回答