为什么我需要手动删除vector中的指针?

时间:2012-08-05 00:32:58

标签: c++ memory-management destructor

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

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

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

4 个答案:

答案 0 :(得分:11)

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

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

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

智能指针自然可以解决这个问题。但是如果你必须使用手册delete来存储在标准容器中的原始指针,那么这将是一个更好的步骤序列

  1. i检索元素的值并将其存储在指针p
  2. 从容器中删除i处的元素
  3. delete p
  4. 最后,您最终得到一个空容器和delete d数据。同样,您的方法适用于简单序列,例如std::vectorstd::list,但不要使用有序或散列的序列。

答案 1 :(得分:6)

因为当你完成时,语言无法知道你是否需要它们保持活力。如果你插入一些指向堆栈对象或类似的东西怎么办?吊杆。

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

答案 2 :(得分:3)

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

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

答案 3 :(得分: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;
    }
}