【问题标题】:Does vector::erase() on a vector of object pointers destroy the object itself?对象指针向量上的 vector::erase() 会破坏对象本身吗?
【发布时间】:2011-09-15 05:44:28
【问题描述】:

我有一个指向对象的指针向量。我需要从向量中删除一个元素并将该元素放在另一个列表中。

我读到擦除可用于从向量中删除对象,但我也读到它在这样做之前调用对象析构函数。

我需要知道擦除对象是否也会破坏它。

【问题讨论】:

标签: c++ stl vector


【解决方案1】:

vector::erase
从向量容器中删除并调用其析构函数,但如果包含的对象是指针,则它不会拥有销毁它的所有权。

您必须在每个包含的指针上显式调用 delete 以删除它指向的内容,例如:

void clearVectorContents( std::vector <YourClass*> & a ) 
{    
    for ( int i = 0; i < a.size(); i++ ) 
    {       
        delete a[i];    
    }    
    a.clear(); 
} 

在标准容器中存储原始指针不是一个好主意。如果您确实需要存储必须由new 分配的资源,那么您应该使用boost::shared_ptr。查看Boost documentation

更通用和优雅的解决方案:
正如@Billy 在 cmets 中指出的那样,该解决方案利用了 for_eachtemplates

// Functor for deleting pointers in vector.
template<class T> class DeleteVector
{
    public:
    // Overloaded () operator.
    // This will be called by for_each() function.
    bool operator()(T x) const
    {
        // Delete pointer.
        delete x;
        return true;
    }
};

这可以称为:

for_each( myclassVector.begin(),myclassVector.end(),
          DeleteVector<myclass*>());

其中,myclassVector 是您的向量,其中包含指向 myclass 类对象的指针。

用法示例:

#include "functional"
#include "vector"
#include "algorithm"
#include "iostream"

//Your class
class myclass
{
    public:
        int i;
        myclass():i(10){}
};


// Functor for deleting pointers in vector.
template<class T> class DeleteVector
{
    public:
    // Overloaded () operator.
    // This will be called by for_each() function.
    bool operator()(T x) const
    {
        // Delete pointer.
        delete x;
        return true;
    }
};


int main()
{
    // Add 10 objects to the vector.
    std::vector<myclass*> myclassVector;

    for( int Index = 0; Index < 10; ++Index )
    {
        myclassVector.push_back( new myclass);
    }

    for (int i=0; i<myclassVector.size(); i++) 
    {
        std::cout << " " << (myclassVector[i])->i;
    }

    // Now delete the vector contents in a single  line.
    for_each( myclassVector.begin(),
              myclassVector.end(),
              DeleteVector<myclass*>());

    //Clear the vector 
    myclassVector.clear();

    std::cout<<"\n"<<myclassVector.size();

    return 0;
}

【讨论】:

  • 那么这是否意味着如果它是一个指针向量,则不会调用析构函数?
  • +1 表示完整,说"but If the contained object is a pointer it doesnt take ownership of destroying it."
  • @anonymous 没错。指针本身将被销毁,但由程序员明确释放它所引用的内存(假设内存没有在其他地方使用)。
  • 感谢关于 boost 的提示。将来可能会有所帮助。我目前正在使用游戏引擎 cocos2d-x,据说它会自动执行垃圾收集。
  • 哦,因为您的回答涵盖了所有内容,所以我选择了您的回答。谢谢!
【解决方案2】:
  • 如果您有vector&lt;MyObject&gt;,那么MyObject::~MyObject 将是 调用。
  • 如果您有vector&lt;MyObject*&gt;,则不会调用delete <MyObject instance>

要在两个向量之间移动 MyObject,您需要先将其插入到目标向量中,然后擦除原始向量。请注意,这将创建对象的新副本。移动指针时,您可以将指针保存在临时变量中,将其从向量中擦除,然后插入到您需要的任何位置。

这是另一种简单的方法来删除然后删除向量中的所有项目:

template<class T> void purge( std::vector<T> & v ) {
    for ( auto item : v ) delete item;
    v.clear();
}

【讨论】:

    【解决方案3】:

    是的,erase 会破坏元素。但是,如果您将元素放在另一个容器中,您可能会制作一个副本,将其放入另一个容器中。遇到问题的唯一方法是将指针或类似的东西复制到另一个容器中。

    【讨论】:

    • 是的,我正在使用指向对象的指针向量。抱歉,我没有澄清这一点。
    • @anonymous:啊,那么指针的“析构函数”会被调用。当然,什么都不做。向量会破坏它实际包含的内容,而不是从那里引用的任何内容。 (请注意,这意味着您必须手动返回并delete
    • 哦,好吧,所以澄清一下,如果我有:vector&lt;Plane *&gt; p, q;Plane *r = new Plane();p.push_back(r);q.push_back(r);p.erase(p.begin());r 和 q.begin() 仍然会引用新创建的平面?
    • 这与您刚刚编写{ Plane * p = new Plane; } 的行为相同,当p 超出范围时,它被“销毁”但分配的对象仍然存在于堆上。使用裸指针使它们你的责任。
    【解决方案4】:

    是的。 vector::erase 销毁被移除的对象,这涉及到调用它的析构函数。

    【讨论】:

      【解决方案5】:

      是的,当然会。如果向量中不存在该对象,它还会存在于哪里?

      编辑:这将不会删除指针指向的任何内容。您应该使用自动生命周期管理指针,例如 shared_ptr 来管理对象生命周期。

      【讨论】:

        猜你喜欢
        • 2012-10-24
        • 2021-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-01
        • 2016-10-29
        • 2011-02-11
        • 1970-01-01
        相关资源
        最近更新 更多