2012-04-19 3 views
0

У меня есть вектор указателей как так:удаление вещи из вектора указателей

vector<Item*> items; 

Я хочу, чтобы очистить его. Я пробовал:

for (unsigned int i = 0; i < items.size(); i++) 
    delete items.at(i); 
items.clear(); 

,

while (!items.empty()) 
{ 
    delete items.back(); 
    items.pop_back(); 
} 

,

while (!items.empty()) 
{ 
    delete items.at(0); 
    items.erase(items.begin()); 
} 

и

while (!items.empty()) 
    delete items.at(0); 

Каждый из этих ударов вверх по той или иной причине, включая удаление уже удаленных объектов и исключение f итераторы вектора диапазона.

Что мне делать? Я хочу, чтобы иметь возможность повторно использовать тот же вектор и добавить в него дополнительные указатели. Просто используя delete без очистки все еще оставляет указатели мусора там, правильно?

EDIT: Хорошо, я переключился на shared_ptrs. Теперь у меня есть

vector<shared_ptr<Item> > items; 

Тем не менее, когда я items.clear();, я получаю ошибку «вектор итераторы несовместимыми». Что я все еще делаю неправильно?

+1

Если у вас есть вектор указателей, используйте умные указатели (которые вы должны делать в любом случае). – chris

+0

Как это использовать? :/ – Pojo

+0

google for boost :: shared_ptr –

ответ

0

Ну, я сделал это. После много времени, много аспирина и много потерянных волос, я наконец выяснил, в чем проблема. Оказывается, я раньше вызывал конкретного деструктора, в котором содержался класс, содержащий этот вектор указателей. Я понятия не имел, что только , вызывающий, деструктор заставит его стереть все статические элементы данных. Иногда я ненавижу C++.

0

Либо использовать вектор смарт-указатели, как это:

vector<shared_ptr<Item> > myVect; 

Или использовать Pointer Containers библиотеку импульс.

Возможно, есть способ сделать это и повторно использовать вещи, но, похоже, он подвержен ошибкам и намного больше работает, особенно учитывая, что контейнеры-указатели в boost - это библиотека только для заголовков.

+0

Хм, теперь как я могу очистить этот вектор? У меня есть 'vector > items;' now, и когда я делаю 'items.clear();', я получаю ошибку «векторные итераторы несовместимы». – Pojo

0

использовать boost::shared_ptr<Item>, и они будут удалены при удалении вектора или удалении элемента.

0

Что мне делать?

Не поддерживать вектор указателей. На самом деле, это почти всегда ошибка, и вы боретесь с дизайном вектора (RAII), который заботится об управлении памятью для вас. Теперь вам нужно вызвать delete на каждый указатель.

Вам действительно нужен вектор указателей? Если вы действительно do (не просто думайте, что делаете, но на самом деле это требование по той или иной причине), то используйте умные указатели.

Вектор будет динамически выделять память для вас, просто используйте ее так, как она была предназначена для использования.

2

Я проверил тест со всеми вашими способами удаления вещей, и один из них просто не работает. См. Код ниже для комментариев к ним.

Чтобы ответить на ваш вопрос: «Что мне делать,» вот то, что я делаю, когда SEG-неисправность на удаление:
1) Убедитесь в том, что память моя (я знаю, где соответствующая новая есть)?
2) Убедитесь, что я уже не удалял память (если бы я это сделал, даже если бы он был моим, это не сейчас).

3) Если вы уверены, что ваш seg-fault вызван одной частью вашего кода, выведите его в небольшой тестовый пример в другом проекте (вроде как в вашем вопросе). Тогда играйте с ним. Если вы запустили примеры кода вверху в небольшом проекте, вы бы увидели seg-fault на последнем, и вы бы отметили, что удаленные работы выполнялись в каждом другом случае. Нарушение кода таким образом позволило бы вам узнать, что вам нужно проследить, как вы храните их в своем векторе, чтобы узнать, где вы теряете право собственности на них (через удаление или передачу их на что-то, что их удаляет, и т. Д.).).

Замечание: как говорят другие, если вы можете использовать интеллектуальные указатели, то они позаботятся об управлении памятью для вас. Однако, пожалуйста, продолжите свое исследование здесь и поймите, как использовать указатели, которые глупы. Бывают случаи, когда вы не можете импортировать boost, или QT делает ваше управление памятью для вас. Кроме того, есть моменты, когда вы ДОЛЖНЫ хранить указатели в контейнере, поэтому не бойтесь это делать (разработчики IE: QT STRONGLY предлагают использовать указатели для хранения виджетов вместо ссылок или чего-либо подобного).

#include <vector> 

using namespace std; 
class Item 
{ 
public: 
    int a; 
}; 

int main() 
{ 
    vector<Item *> data; 

    for(int x = 0; x < 100; x++) 
    { 
     data.push_back(new Item()); 
    } 

    //worked for me, and makes sense 
    for(int x = 0; x < 100; x++) 
    { 
     delete data.at(x); 
    } 
    data.clear(); 

    for(int x = 0; x < 100; x++) 
    { 
     data.push_back(new Item()); 
    } 
    //worked for me, and makes sense 
    while (!data.empty()) 
    { 
     delete data.back(); 
     data.pop_back(); 
    } 
    data.clear(); 

    for(int x = 0; x < 100; x++) 
    { 
     data.push_back(new Item()); 
    } 

    // //worked for me, and makes sense 
    while (!data.empty()) 
    { 
     delete data.at(0); 
     data.erase(data.begin()); 
    } 

    for(int x = 0; x < 100; x++) 
    { 
     data.push_back(new Item()); 
    } 

// //This one fails, you are always trying to delete the 0th position in 
// //data while never removing an element (you are trying to delete deleted memory) 
// while (!data.empty()) 
// { 
//  delete data.at(0); 
// } 


    return 0; 
} 
0

Звучит так, как будто у вас одни и те же указатели (ы), повторяющиеся в вашем векторе. Чтобы быть уверенным, что вы удаляете их только один раз, переведите их на std::set и удалите их там. Например,

std::set<Item*> s(items.begin(), items.end()); 
items.clear(); 

while (!s.empty()) 
{ 
    delete *s.begin(); 
    s.erase(s.begin()); 
}