Удалить все элементы из С++ std::vector

Я пытаюсь удалить все из std::vector, используя следующий код

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

но это не работает.


Обновление: не очищает ли удаление элементов, удерживаемых вектором? Я не хочу этого, поскольку я все еще использую объекты, я просто хочу очистить контейнер.


person michael    schedule 06.10.2009    source источник
comment
ясно() есть. ты можешь использовать это   -  person vpram86    schedule 06.10.2009
comment
Обновление ничего не проясняет. Что такое векторные элементы? Это указатели или объекты? Если они являются объектами, как они все еще используются? Почему вы хотите очистить вектор?   -  person David Thornley    schedule 06.10.2009
comment
1. Что не работает? 2. Неужели вы не знаете разницы между указателями и указателями? Если вы сохраните указатели в векторе, а затем вызовете clear(), он уничтожит указатели, а не указатели!   -  person sellibitze    schedule 06.10.2009
comment
Ваше редактирование кажется немного запутанным. Вектор владеет хранящимися в нем объектами. Если вы удаляете объекты из вектора, то копии уничтожаются. Это неизбежно, им негде жить. Их увозят с места, где они хранились. Если вы этого не хотите, вы не можете осмысленно очистить контейнер.   -  person jalf    schedule 06.10.2009
comment
См. аналогичный вопрос: stackoverflow.com/questions/1514311/   -  person John Carter    schedule 07.10.2009


Ответы (9)


Я думаю, вам следует использовать 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(); 
person AraK    schedule 06.10.2009
comment
Если ваш вектор содержит указатели, это не освободит память, а просто очистит коллекцию. Вы должны освободить память самостоятельно. - person Patrice Bernassola; 06.10.2009
comment
@Patrice Конечно, но спрашивающий ничего не сказал о содержании вектора. - person AraK; 06.10.2009
comment
Поэтому я добавил информацию. В любом случае я согласен с вашим ответом. - person Patrice Bernassola; 06.10.2009
comment
Это было связано с тем, как я получал вектор. - person michael; 06.10.2009
comment
@Michael Возможно, getVector() возвращает копию m_vector, а не ссылку. - person AraK; 06.10.2009
comment
Если бы проблема OP действительно была связана с v.erase( v.begin(), v.end() ), просто рекомендация v.clear() не помогла бы, поскольку это не более чем псевдоним для первого. - person DevSolar; 06.10.2009
comment
@michael: Можете ли вы опубликовать подпись getVector ()? - person Naveen; 06.10.2009
comment
clear() вообще память не освобождает - просто все уничтожает и помечает как неиспользуемое (но привязанное к вектору). Если вы хотите по-настоящему освободить память, попробуйте myvector.swap(std::vector<content_type>()); - person bdonlan; 06.10.2009
comment
@bdonlan Хотя в стандартах ничего не говорится о новой емкости вектора после четкой операции, я думаю, вы правильно заметили, как с этим справляются реализации. Я отредактирую сообщение, чтобы указать размер, а не емкость :) - person AraK; 06.10.2009
comment
очень хороший момент, bdonlan, clear() не меняет емкость(), если реализация несколько умна, что я ценю из реализации стандарта! - person Gabriel; 11.02.2015
comment
В приведенном выше примере, если myclass имеет такой векторный элемент, как std::vector<int> data;. Затем myclass должен очистить это в destructor, позвонив data.clear(). Например, ~myclass() {data.clear();}. - person shuva; 25.09.2017

vector.clear() должен работать на вас. Если вы хотите уменьшить емкость vector вместе с очисткой,

std::vector<T>(v).swap(v);
person aJ.    schedule 06.10.2009
comment
Поменять местами с самим собой? .. Разве его обычно не заменяют новым пустым вектором? - person Macke; 06.10.2009
comment
да. После очистки вектор будет пуст. std::vector‹T›(v).swap(v) — это общий способ уменьшения емкости вектора. - person aJ.; 06.10.2009
comment
Этот метод также обсуждается в одной из статей журнала Herb Sutter «Гуру недели»: gotw.ca/gotw/ 054.htm - person Void; 07.10.2009
comment
и теперь у вас есть Friction_to_fit() , который может выполнять ту же работу, что и раньше, под капотом. - person Abhinav Gauniyal; 09.04.2015

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.

person DevSolar    schedule 06.10.2009
comment
В случае стирания я думал, что итератор может стать недействительным после первого стирания. Правильно ли я понимаю или я что-то упускаю? - person Naveen; 06.10.2009
comment
Он не очищает вектор, а просто удаляет элементы. Я бы предложил дополнительно установить значения указателя равными нулю, а затем очистить вектор. - person unknownuser; 06.10.2009
comment
стереть(сначала итератор, потом итератор); определен для работы с диапазонами элементов, включая диапазон begin()-end(). Я не уверен на 100%, что v.clear() даже официально не определен с точки зрения v.erase( v.begin(), v.end() ), но это определенно в наименее функционально идентичны. - person DevSolar; 06.10.2009
comment
Не компилируется на сегодняшний день! use of class template requires template arguments - person Mohammad Kanan; 16.05.2020
comment
@MohammadKanan Должно было быть delete_pointer_element<int*>(), но в любом случае оно стало устаревшим из-за диапазона. - person DevSolar; 16.05.2020

Используйте v.clear(), чтобы очистить вектор.

Если ваш вектор содержит указатели, clear вызывает деструктор для объекта, но не удаляет память, на которую ссылается указатель.

vector<SomeClass*> v(0);

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

v.clear();  //Memory leak where "one" instance of SomeClass is lost
person Alex B    schedule 06.10.2009

v.clear() по какой-то причине не работает?

person Rob    schedule 06.10.2009
comment
Не очищает ли разрушает элементы, содержащиеся в векторе? Я не хочу этого, поскольку я все еще использую объекты, я просто хочу очистить контейнер. - person michael; 06.10.2009
comment
@michael: Я предполагаю, что вы храните указатели в своем векторе и беспокоитесь об удалении реальных объектов. Это правильно? В этом случае clear() не удалит фактические объекты, а просто очистит только вектор. - person Naveen; 06.10.2009
comment
clear() не уничтожает элементы, содержащиеся в векторе. Это только очистить коллекцию объектов. - person Patrice Bernassola; 06.10.2009

Если вы храните указатели в контейнере и не хотите возиться с их ручным уничтожением, используйте повысить 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;
}
person Dominic.wig    schedule 06.10.2009

Добавление к вышеупомянутым преимуществам swap(). Это clear() не гарантирует освобождение памяти. Вы можете использовать swap() следующим образом:

std::vector<T>().swap(myvector);
person Samer    schedule 05.02.2015
comment
Согласно комментарию ниже: stackoverflow.com/questions/1525535/, clear(), тогда swap() будет работать правильно. - person Manohar Reddy Poreddy; 13.09.2016

Если ваш вектор выглядит так std::vector<MyClass*> vecType_pt, вы должны явно освободить память. Или, если ваш вектор выглядит так: std::vector<MyClass> vecType_obj, конструктор будет вызываться вектором. Пожалуйста, выполните пример, приведенный ниже, и поймите разницу:

  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;
    }
person Satbir    schedule 06.10.2009

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();

person Sinipelto    schedule 18.02.2018