C ++ удалить вектор указателей - PullRequest
3 голосов
/ 28 декабря 2011

Вот мой код:

#include <vector>
#include <stdio.h>
#include <iostream>

using namespace std;

class Foo 
{
public:
    Foo()
    {
    }
    ~Foo()
    {
    }
    void Bar()
    {
        cout << "bar" << endl;
    }
};

template <class T>
void deleteVectorOfPointers( T * inVectorOfPointers )
{
    typename T::iterator i;
    for ( i = inVectorOfPointers->begin() ; i < inVectorOfPointers->end(); i++ )
    {
        delete * i;
    }
    delete inVectorOfPointers;
}

int main()
{
    //create pointer to a vector of pointers to foo
    vector<Foo*>* pMyVec = new vector<Foo*>();
    //create a pointer to foo
    Foo* pMyFoo = new Foo();
    //add new foo pointer to pMyVec
    pMyVec->push_back(pMyFoo);
    //call Bar on 0th Foo element of pMyVec
    pMyVec->at(0)->Bar();
    //attempt to delete the pointers inside the vector and the vector itself
    deleteVectorOfPointers(pMyVec);
    //call Bar on 0th Foo element of pMyVec
    pMyVec->at(0)->Bar();
    //call Bar directly from the pointer created in this scope
    pMyFoo->Bar();
    return 0;
}

Я пытаюсь удалить указатель на вектор, а также все указатели внутри вектора.Тем не менее, Бар все еще работает очень хорошо после того, как я пытаюсь это сделать ...

Ответы [ 6 ]

5 голосов
/ 28 декабря 2011

Это вызывает неопределенное поведение. Это означает, что все может случиться. Это:

*reinterpret_cast<int*>(0x12345678) = 314159;

тоже может сработать ... И что?

2 голосов
/ 28 декабря 2011

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

Указатель все еще имеет свое первоначальное значение, но он указывает на память, которая больше не принадлежит вам.
Доступ к памяти, которая не принадлежит вам, не определена.

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

2 голосов
/ 28 декабря 2011

Приведенный выше код работает, потому что он на самом деле не полагается на наличие экземпляра Foo.Переменные экземпляра не используются, поэтому он никогда не обращается к этой памяти.Конечно, это не делает его безопасным, это просто означает, что он работал в данном конкретном случае.Возьмем следующий пример:

#include <vector>
#include <iostream>
#include <string>

using namespace std;

class Foo
{
private:
  std::string greet;    
public:
  Foo() : greet("Hello.") {}
  ~Foo() { cout << "Done." << endl; }
  void bar() { cout << greet << endl; };
};

template <class T>
void deleteVectorOfPointers(T *vector) {
  typename T::iterator i;
  for (i = vector->begin(); i < vector->end(); ++i) {
    delete *i;
  }
  delete vector;
}

int main()
{
  vector<Foo *> *myVector = new vector<Foo *>();
  Foo *testObj = new Foo();
  myVector->push_back(testObj);
  myVector->at(0)->bar();
  deleteVectorOfPointers(myVector);
  testObj->bar();
  return 0;
}

Это происходит с ошибками, как и ожидалось, поскольку bar () пыталась получить доступ к переменной экземпляра, которой больше нет.

2 голосов
/ 28 декабря 2011

что вы указали, это неопределенное поведение. вектор и объект foo () действительно удалены ...

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

1 голос
/ 28 декабря 2011

Стоит рассмотреть ptr_vector вместо вектора для хранения указателей.

http://www.boost.org/doc/libs/1_48_0/libs/ptr_container/doc/ptr_vector.html

Вы должны помнить, что доступ к удаленным данным не всегда направлен на segfault. Иногда нет новых данных на месте пожилых людей. удаление не очистило пространство памяти.

пример пространства памяти:

[х _] [Y] [ Z ]

после удаления Z:

[x _] [y] [ Z ]

, что Z может быть допустимым какое-то время, но это неопределенное поведение, потому что Z теперь только мусор.

0 голосов
/ 29 декабря 2011

Это МОЖЕТ работать правильно только потому, что ваша функция Foo :: Bar действительно никогда не обращается к объекту * this.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...