2014-03-21 3 views
0

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

Рассмотрим простой класс:

class Obj 
{ 
public: 
    Obj(int moose); 
    ~Obj(); 

private: 
    int* val; 
}; 


Obj::Obj(int num) 
{ 
    val = new int; 

    *val = num; 
} 


Obj::~Obj() 
{ 
    printf("Cleanup"); 
    delete val; 
} 

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

int main(int argc, const char * argv[]) 
{ 
    std::vector<Obj*> objs; 

    Obj* o = new Obj(10); 

    objs.push_back(o); 

    objs.erase(objs.begin() + 0); 

    // should have been deleted by now - I want the destructor to have been called 
    // I have tried delete objs[0], casting to it and then deleting it. 

    return 0; 
} 

Деструктор в Obj вызывается только при завершении программы. Я хочу, чтобы он вызывался, когда объект удаляется из вектора.

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

Edit:

Даже после добавления:

auto it = objs.begin() + 0; 
delete *it; 
objs.erase(it); 

как предложено, деструктор Obj не срабатывает.

+1

Тогда вам нужно будет использовать 'delete', прежде чем удалять его, или использовать что-то вроде контейнера интеллектуальных указателей или' ptr_vector' Boost. – chris

+2

'std :: vector <>' не разрушает его элементы, он просто удаляет их из контейнера. Вам нужно удалить память. – 0x499602D2

+0

Вы хотите использовать shared_ptr или ptr_vector http://stackoverflow.com/questions/10790161/shared-ptr-with-vector – Daniel

ответ

3

Как указано в комментариях, vector.erase удаляет только элементы из вектора. Он НЕ пытается удалить связанную память.
Чтобы удалить связанную с ним память явно, что вам нужно:

int main(int argc, const char * argv[]) 
{ 
    ... 

    auto it = objs.begin() + i; 
    delete *it; 
    objs.erase(it); 

} 

На самом деле, в вашем случае:

int main(int argc, const char * argv[]) 
{ 
    std::vector<Obj*> objs; 

    Obj* o = new Obj(10); 
    objs.push_back(o);  

    auto it = objs.begin(); 
    delete *it; 
    objs.erase(it); 

} 

Есть целый ряд других несоответствий с вашим кодом и, более эффективных решений для чего вы «вновь пытается сделать, такие как:

  • Использование vector<Obj>:

    int main(int argc, const char * argv[]) 
    { 
        std::vector<Obj> objs; 
        objs.emplace_back(10);  
    
        auto it = objs.begin(); 
        objs.erase(it); 
    } 
    
  • Если вам необходимо динамически выделять свои объекты, но по каким-то причинам не хотят вектор справиться с этим, вы можете использовать shared_ptr или unique_ptr, который будет заботиться о открепления для вас:

    int main(int argc, const char * argv[]) 
    { 
        std::vector<std::unique_ptr<Obj>> objs; 
    
        objs.emplace_back(new Obj(10));  
    
        auto it = objs.begin(); 
        objs.erase(it); 
    } 
    
+0

О, хорошо, мое плохое, отредактирует –

+0

Используя ваши примеры, я все еще не получаю деструктор моего класса Obj для стрельбы. Это проблема, с которой я столкнулся. – user923

+0

Я фактически протестировал три версии кода, который я опубликовал, и все они, похоже, правильно уничтожают объект. В одной версии вкратце был оператор 'delete []', потому что я неправильно понял ваш код, так что, может быть, это версия, которую вы пытаетесь использовать? –

1

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

+0

Я все еще не могу заставить деструктор стрелять при удалении объекта. – user923

+0

Что-то подобное 'delete objs [0]' будет вызывать деструктор. Вы должны удалить объект из вектора, если он вам не нужен, но вы также должны называть 'delete o' или' delete objs [0] '. – user1717884

+0

Как вы удаляете объект и проверяете, был ли вызван деструктор до завершения программы? – user1717884

0

Когда вы удаляете элемент из вектора, вызывается деструктор элемента. Но в этом случае элемент является указателем, а указатели не имеют деструкторов. Объект, на который указывает указатель, будет не имеет свой деструктор, пока вы не нажмете delete на указатель. Если указатель стирается и у вас нет другой копии, вы никогда не сможете его удалить, и у вас будет утечка памяти.

По возможности предпочитайте поместить объект непосредственно в вектор, а не в указатель. Это облегчит вам работу по управлению памятью.

+0

Спасибо. Конкретная проблема, которую я имею здесь, заключается в том, что когда я удаляю объект, деструктор не срабатывает, пока программа не закончится. – user923

+0

@ user923 вы удаляете 'val', но для этого вам нужно сначала удалить' o'. Я не вижу этого в коде, который вы опубликовали. –

+0

auto it = objs.begin() + 0; delete * it; objs.erase (it); – user923

Смежные вопросы