Может ли утечка памяти при использовании вектора указателя в с ++?

Я пробовал это:

....
vector<players*> player;
for (int i = 0; i<10; i++)
{
    player.push_back(new players());
}
...

А мне интересно, а надо ли для вектора освобождать память? Если да, то как?


person Community    schedule 01.04.2010    source источник


Ответы (3)


Если вам нужно хранить указатели на объекты в контейнере, вы должны либо сохранить какой-то интеллектуальный указатель (например, std::tr1::shared_ptr или boost::shared_ptr), либо использовать контейнер, предназначенный для хранения указателей, подобных тем, которые находятся в Библиотека контейнеров указателей Boost.

Если вы храните голые указатели, вам нужно не забыть удалить указатели в контейнере до того, как контейнер будет уничтожен. Это включает в себя всякий раз, когда генерируется исключение, которое может привести к разрушению контейнера. Делать это правильно утомительно, чревато ошибками и совершенно ненужно с учетом возможностей, упомянутых в предыдущем абзаце.

person James McNellis    schedule 01.04.2010
comment
Стоит упомянуть, что с C++0x идет unique_ptr, который отлично подходит для такого рода задач. При гораздо меньших накладных расходах shared_ptr. - person Matthieu M.; 01.04.2010

Да, вам нужно delete их самостоятельно. Вектор будет только «разрушать» указатели (что ничего не делает).

По возможности используйте библиотеку контейнеров указателей Boost, и вам не придется об этом беспокоиться. Однако, если вы не можете, вам нужно завернуть контейнер. Предположим, что между заполнением контейнера и удалением его элементов возникает исключение. Вы не выполняете код удаления элемента и утечки.

Простая оболочка может выглядеть так:

struct default_deleter
{
    template <typename T>
    void operator()(T* pPtr)
    {
        delete pPtr;
    }

};

template <typename T, typename Deleter = default_deleter>
struct container_wrapper
{
    typedef T container_type;
    typedef Deleter deleter_type;

    container_wrapper(container_type pContainer = container_type()) :
    container(pContainer)
    {}

    ~container_wrapper(void)
    {
         std::for_each(container.begin(), container.end(), deleter_type());
    }

    container_type container;
};

Используйте это как:

typedef std::vector<int*> vec_intptr;
typedef container_wrapper<vec_intptr> vec;

vec v;
v.container.push_back(new int); // and never worry about it again

Это простая оболочка. Любые операции pop_back(), erase() и т. Д. Будут иметь неправильный эффект. Я настоятельно рекомендую использовать Boost.

Можно подумать об использовании контейнера с auto_ptr. Наоборот, это плохая идея; семантика копирования auto_ptr не позволяет ему работать. Лучше всего по возможности избавиться от динамического выделения.

person GManNickG    schedule 01.04.2010
comment
Я не знаю, можем ли мы использовать автопоинтеры в векторе. gotw.ca/publications/using_auto_ptr_effectively.htm - person Samrat Patil; 01.04.2010
comment
@Sammy, нельзя использовать auto_ptr в контейнерах STL. Можно сделать это с помощью контейнера указателя ускорения lib. - person vladr; 01.04.2010
comment
@GMan, последнее container_wrapper утверждение может вводить в заблуждение; OP все еще должен волноваться, если он когда-нибудь решит позвонить v.container.erase, v.container.clear и т. д. - person vladr; 01.04.2010
comment
@Vlad: Согласен, упомяну. - person GManNickG; 01.04.2010

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

person yamspog    schedule 01.04.2010