C++ 为什么我需要手动删除向量中的指针?

C++ 为什么我需要手动删除向量中的指针?,c++,memory-management,destructor,C++,Memory Management,Destructor,为什么我需要手动删除vector中动态创建的项?为什么它们不会被删除,或者在向量被删除时调用它的析构函数 通常是这样的,但为什么需要呢 vector<int*> v; for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it) { delete *it; } 向量v; for(vector::iterator it=v.begin();it!=v.end();++it) { 删除*它;

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

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

vector<int*> v;
for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it) 
{ 
   delete *it; 
}
向量v; for(vector::iterator it=v.begin();it!=v.end();++it) { 删除*它; }
向量的实现只是为了删除它的内存。指针没有解构器。而在C++中,没有垃圾收集或逻辑来查看它是指针和递归删除它。
如果您想参加下一次ISO会议并提议,请成为我的嘉宾,但对我来说,我只是将其放入
内联
函数中:

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;
    }
}
模板
公共静态内联void deleteVectorPointer(std::vector v)
{
对于(向量::迭代器i=v.begin();i!=v.end();i++)
{
删除*i;
}
}

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


在C++11中,
std::unique_ptr
确实拥有它所指向的对象。在本例中,释放指针时调用析构函数,这可能是您想要的行为。(如果您没有C++11编译器,但有一个相当新的前C++11编译器,
unique_ptr
仍然作为TR1的一部分提供。)

因为语言无法知道您是否需要它们在完成后保持活动状态。如果您插入一些指向堆栈对象或类似对象的指针,会怎么样?轰


但是,这可以通过使用智能指针来解决,智能指针将实现自动销毁的适当策略
unique_ptr
shared_ptr
是最常见和最有用的。首先,在向量中存储原始指针。这些指针只是指针。他们可以指向任何地方。它们可以指向本地对象,
delete
无法删除这些对象。即使它们指向动态创建的对象,也不一定意味着用户希望它们与向量一起消亡。向量怎么会知道这些

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

其次,请注意,在一般情况下,您的删除技术不一定是安全的。一些标准容器假定存储在其中的数据始终有效。当您在每个向量元素上执行
delete
操作时,向量中的数据将变为“无效”(指针变得不确定)。这是一个向量。但在“更智能”的容器中执行类似操作,例如
std::map
std::unordered_set
,可能并将导致问题。即使随后立即销毁容器本身,容器的销毁算法也完全可能需要分析(比较、散列等)单个元素的值。你用你的自行车把他们都杀了

聪明的指针自然会解决这个问题。但是,如果必须对存储在标准容器中的原始指针使用手动
delete
,则更好的步骤顺序是

  • i
    处检索元素的值,并将其存储在指针
    p
  • 从容器中删除
    i
    处的元素
  • 是否删除p

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

    如果您有指针向量,它将获得指针的RID。不会调用析构函数,因为指针本身没有析构函数。@Ynau他在问为什么必须删除指针上的数据。vector怎么知道您的项是“动态创建的”?在向量中存储指针。指针可以指向任何地方。它们可以指向动态对象。它们可以指向静态对象。它们都可以指向同一个局部对象。你认为向量应该如何识别和处理所有这些情况呢?
    std::vector
    可以做到,不需要任何清理功能。C++11并不认为这很糟糕:而且在11之前就有很多实现可以接受
    >
    。只有在C++11中才是标准的。回答很好,关于过早删除
    std::map
    等中的元素的危险性,我不理解在
    std::map
    中删除元素的问题。删除指针不会改变它的值,对吗?@rafak:当你有一个存储指针的
    std::map
    时,大多数时候你会使用一个比较函数来比较指针对象,而不是指针本身。但你已经摧毁了那些尖锐的物体。因此,如果在那一刻之后,地图出于某种原因决定进行比较,它将失败。这实际上取决于实施情况<代码>标准::映射我看到的实现不会这样做。但是GCC实现中的
    hash_-map
    :如果预先删除这样的指向对象,它将在析构函数中崩溃。@AndreyT:好的,谢谢你的精确性。我以为你指的是比较指向不在同一数组中的对象的指针的不特定性。