【问题标题】:Delete all items from a c++ std::vector从 c++ std::vector 中删除所有项目
【发布时间】:2010-12-04 06:37:16
【问题描述】:

我正在尝试使用以下代码从std::vector 中删除所有内容

vector.erase( vector.begin(), vector.end() );

但它不起作用。


更新:不清除破坏向量持有的元素吗?我不想这样,因为我还在使用这些对象,我只想清空容器

【问题讨论】:

  • clear() 在那里。你可以用它
  • 更新没有澄清事情。向量元素究竟是什么?它们是指针还是对象?如果它们是对象,它们如何仍在使用中?为什么要清空向量?
  • 1.什么不起作用? 2.难道你不知道指针和指针的区别吗?如果将指针存储在向量中,然后调用 clear() 它将破坏指针,而不是指针!
  • 您的编辑似乎有点混乱。向量拥有存储在其中的对象。如果您从向量中移除对象,则副本将被销毁。这是不可避免的,他们无处可住。它们正被从存放它们的地方移走。如果您不希望这样,那么您就无法有意义地“清空容器”。
  • 看到这个类似的问题:stackoverflow.com/questions/1514311/…

标签: c++ stl vector


【解决方案1】:

我认为你应该使用std::vector::clear:

vec.clear();

编辑:

不清除破坏元素 被向量持有?

是的。它在返回内存之前调用向量中每个元素的析构函数。这取决于您在向量中存储的“元素”。在下面的示例中,我将对象自身存储在向量中:

class myclass
{
public:
    ~myclass()
    {

    }
...
};

std::vector<myclass> myvector;
...
myvector.clear(); // calling clear will do the following:
// 1) invoke the deconstrutor for every myclass
// 2) size == 0 (the vector contained the actual objects).

例如,如果您想在不同容器之间共享对象,您可以存储指向它们的指针。在这种情况下,当clear被调用时,只释放指针内存,不触及实际对象:

std::vector<myclass*> myvector;
...
myvector.clear(); // calling clear will do:
// 1) ---------------
// 2) size == 0 (the vector contained "pointers" not the actual objects).

对于评论中的问题,我认为getVector()是这样定义的:

std::vector<myclass> getVector();

也许你想返回一个参考:

// vector.getVector().clear() clears m_vector in this case
std::vector<myclass>& getVector(); 

【讨论】:

  • 如果你的向量包含指针,这不会释放内存,只是清除集合。你必须自己释放内存。
  • @Patrice 当然,但提问者对向量的内容只字未提。
  • 这就是我添加信息的原因。无论如何我同意你的回答。
  • @Michael 也许 getVector() 返回 m_vector 的 copy 而不是引用。
  • clear() 通常不会释放内存 - 它只会破坏所有内容并将其标记为未使用(但绑定到向量)。如果你想真正释放内存,试试myvector.swap(std::vector&lt;content_type&gt;());
【解决方案2】:

vector.clear() 应该适合你。如果您想缩小 vector 的容量以及 clear 然后

std::vector<T>(v).swap(v);

【讨论】:

  • 自己换? .. 通常不会用新的空向量交换它吗?
  • 是的。清除后,向量将为空。 std::vector(v).swap(v) -- 是一种缩小向量容量的通用方法。
  • Herb Sutter 的“本周大师”文章中也讨论了这种技术:gotw.ca/gotw/054.htm
  • 现在你有了 shrink_to_fit() ,它可能正在做同样的工作,在引擎盖下。
【解决方案3】:

vector.clear() 实际上与 vector.erase(vector.begin(), vector.end()) 相同。

如果您的问题是为向量中包含的每个指针调用delete,试试这个:

#include <algorithm>

template< typename T >
struct delete_pointer_element
{
    void operator()( T element ) const
    {
        delete element;
    }
};

// ...
std::for_each( vector.begin(), vector.end(), delete_pointer_element<int*>() );

编辑:代码被 C++11 range-for 废弃。

【讨论】:

  • 在擦除的情况下,我认为迭代器可能在第一次擦除后变得无效。我的理解是正确的还是我遗漏了什么?
  • 他没有清除向量,只是删除了元素。我建议另外将指针值设置为空,然后清除向量。
  • 擦除(首先迭代器,最后迭代器);被定义 用于元素跨度,其中包括 begin()-end() 跨度。我不是 100% 确定 v.clear() 是否没有正式定义 就 v.erase( v.begin(), v.end() ) 而言,但它肯定是至少功能相同。
  • 今天不编译! use of class template requires template arguments
  • @MohammadKanan 应该是 delete_pointer_element&lt;int*&gt;(),但无论如何已经被 range-for 淘汰了。
【解决方案4】:

使用v.clear() 清空向量。

如果你的向量包含指针,clear 会调用对象的析构函数,但不会删除指针引用的内存。

vector<SomeClass*> v(0);

v.push_back( new SomeClass("one") );

v.clear();  //Memory leak where "one" instance of SomeClass is lost

【讨论】:

    【解决方案5】:

    v.clear() 是否由于某种原因无法正常工作?

    【讨论】:

    • 不清除破坏向量持有的元素吗?我不希望这样,因为我仍在使用这些对象,我只想清空容器
    • @michael:我的猜测是您将指针存储在向量中并担心实际对象被删除。它是否正确?在这种情况下, clear() 不会删除实际的对象,它只会清除向量。
    • clear() 不会破坏向量中的元素。它只清除对象的集合。
    【解决方案6】:

    如果您将指针保存在容器中并且不想手动销毁它们,请使用boost shared_ptr。这是 std::vector 的示例,但您可以将它用于任何其他 STL 容器(集合、映射、队列……)

    #include <iostream>
    #include <vector>
    #include <boost/shared_ptr.hpp>
    
    struct foo
    {
        foo( const int i_x ) : d_x( i_x )
        {
            std::cout << "foo::foo " << d_x << std::endl;
        }
    
        ~foo()
        {
            std::cout << "foo::~foo " << d_x << std::endl;
        }
    
        int d_x;
    };
    
    typedef boost::shared_ptr< foo > smart_foo_t;
    
    int main()
    {
        std::vector< smart_foo_t > foos;
        for ( int i = 0; i < 10; ++i )
        {
            smart_foo_t f( new foo( i ) );
            foos.push_back( f );
        }
    
        foos.clear();
    
        return 0;
    }
    

    【讨论】:

      【解决方案7】:

      除了上面提到的swap(). 的好处之外,clear() 并不能保证内存的释放。您可以使用swap(),如下所示:

      std::vector<T>().swap(myvector);
      

      【讨论】:

      【解决方案8】:

      如果你的vector看起来像std::vector&lt;MyClass*&gt; vecType_pt你必须显式释放内存,或者如果你的vector看起来像:std::vector&lt;MyClass&gt; vecType_obj,构造函数将被vector调用。请执行下面给出的示例,并理解区别:

        class MyClass
          {
          public:
              MyClass()
              {
                  cout<<"MyClass"<<endl;
              }
              ~MyClass()
              {
                  cout<<"~MyClass"<<endl;
              }
          };
          int main() 
          {
              typedef std::vector<MyClass*> vecType_ptr;
              typedef std::vector<MyClass> vecType_obj;
              vecType_ptr myVec_ptr;
              vecType_obj myVec_obj;
              MyClass obj;
              for(int i=0;i<5;i++)
              {
                  MyClass *ptr=new MyClass();
                  myVec_ptr.push_back(ptr);
                  myVec_obj.push_back(obj);
              }
              cout<<"\n\n---------------------If pointer stored---------------------"<<endl;
              myVec_ptr.erase (myVec_ptr.begin(),myVec_ptr.end());
              cout<<"\n\n---------------------If object stored---------------------"<<endl;
              myVec_obj.erase (myVec_obj.begin(),myVec_obj.end());
              return 0;
          }
      

      【讨论】:

        【解决方案9】:
        class Class;
        std::vector<Class*> vec = some_data;
        
        for (unsigned int i=vec.size(); i>0;) {
            --i;
            delete vec[i];
            vec.pop_back();
        }
        // Free memory, efficient for large sized vector
        vec.shrink_to_fit();
        

        性能:θ(n)

        如果纯对象(不推荐用于大数据类型,那么只需 vec.clear();

        【讨论】:

          猜你喜欢
          • 2014-05-24
          • 2011-05-25
          • 1970-01-01
          • 2013-06-11
          • 1970-01-01
          • 1970-01-01
          • 2018-01-26
          • 2011-07-20
          • 2013-04-20
          相关资源
          最近更新 更多