освобождение указателей - PullRequest
0 голосов
/ 11 ноября 2010

У меня есть указатель списка в виде контейнера типа A (называемого ListA), вектора указателей B. (Каждый объект A является классом контейнера, который имеет атрибут private: std<vector> *B). Затем я объявляю указатель (называемый C, имеющий тот же тип, что и A), создаю цикл for для ListA, чтобы получить все указатели B и помещаю их в C. Когда я завершаю свою программу, я сначала освобождаю ListA, а ListA, в свою очередь, освобождает свой собственный вектор указателей B. Затем я освобождаю указатель C, но программа вылетает.

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

Я делаю не так? Или как решить мои проблемы?

Извините, я поставлю свой код ниже

//Class A
#pragma once

#include "MyContainer.h"
class B;
class A
{
public:
    A();
    ~A();
    MyContainer<B> *pListOfB;
}

A::A()
{
    pListOfB = new MyContainer<B>;
}
A::~A()
{
    if(pListOfB)
    {
        delete pListOfB;
        pListOfB = NULL;
    }
}
//Class C
#pragma once

#include "MyContainer.h"
class B;
class C
{
public:
    C();
    ~C();
    MyContainer<B> *pListOfB;
    void getListOfB(MyContainer<A> *pListOfA);
}

C::C()
{
    pListOfB = new MyContainer<B>;
}
C::~C()
{
    if(pListOfB)
    {
        delete pListOfB;
        pListOfB = NULL;
    }
}
void C::getListOfB(MyContainer<A> *pListOfA)
{
    for(pListOfA->isBegin(); !pListOfA->isEnd();)
    {
        A *pA = pListOfA->getNext();
        for(pA->isBegin(); !pA->isEnd();)
        {
            B* pB = pA->*pListOfB->getNext();
            pListOfB->add(pB);
        }
    }
}
//Class MyContainer
#pragma once

#include <vector>

template <class T> 
class MyContainer
{
public:
    MyContainer(void);
    ~MyContainer(void);
    T* getNext();
    void removeAll();
    void add(T* t);
    void isBegin();
    bool isEnd();   
private:
    std::vector<T*> items;  
    typename std::vector<T*>::iterator it;
};

template <class T> MyContainer<T>::~MyContainer()
{
    removeAll();
}

template <class T> void MyContainer<T>::add(T *t)
{
    items.push_back(t);
}

template <class T> void MyContainer<T>::removeAll()
{
    while(!isEmpty())
    {
        std::vector<T*>::iterator tempIt =items.begin();
        T* t = (*tempIt);
        items.erase(tempIt);
        delete t;
        t=NULL;
    }
}

template <class T>
T* MyContainer<T>::getNext()
{
    if(isEnd() || isEmpty())
        return NULL;    
    return (T*)(*(it++));
}

template <class T>
void MyContainer<T>::isBegin()
{
    it = items.begin();
}

template <class T>
bool MyContainer<T>::isEnd()
{
    return it==items.end();
}

Я делаю следующее действие: 1. Начальный список объекта A: MyContainer * pListOfA; 2. Вставьте данные B в каждый объект A в pListOfA 3. Начальный объект C 4. Вызвать операцию объекта C getListOfB, чтобы получить данные B из pListOfA. 5. Выйти из программы

Сначала запрограммируйте dealloc pListOfA, затем каждый A освободит свой собственный pListOfB. После того, как эта программа освобождает объект C, в свою очередь, атрибут dealloc pListOfB объекта C. Но pListOfB ни на что не указывает, потому что pListOfA освобождает все данные. Так что моя программа вылетает. Я исправляю с помощью rem строку delete pListOfB в dtor класса C, но в этой строке я получил предупреждение об утечке памяти. Это все моя проблема. Пожалуйста, покажи мне правильный путь. Заранее спасибо.

Ответы [ 2 ]

0 голосов
/ 12 ноября 2010

Правильный способ - не использовать простые указатели .

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

Пример кода, который вы разместили, может быть написан полностью без использования указателей:

//Class A
#pragma once

#include "MyContainer.h"
#include "B.h"

class A
{
public:
    A() { };
    ~A() { };
    MyContainer<B> ListOfB;
};

//Class C
#pragma once

#include "MyContainer.h"
#include "B.h"

class C
{
public:
    C() { };
    ~C() { };
    MyContainer<B> ListOfB;
    void getListOfB(MyContainer<A>& ListOfA);
};

void C::getListOfB(MyContainer<A>& ListOfA)
{
    for(ListOfA.isBegin(); !ListOfA.isEnd();)
    {
        A& anA = ListOfA.getNext();
        for(anA.ListOfB.isBegin(); !anA.ListOfB.isEnd();)
        {
            B aB = anA.ListOfB.getNext();
            ListOfB.add(aB);
        }
    }
}

//Class MyContainer
#pragma once

#include <vector>

template <class T> 
class MyContainer
{
public:
    MyContainer(void);
    ~MyContainer(void) { };
    T& getNext();
    void removeAll();
    void add(const T& t);
    void isBegin();
    bool isEnd();   
private:
    std::vector<T> items;  
    typename std::vector<T>::iterator it;
};

template <class T> void MyContainer<T>::add(const T& t)
{
    items.push_back(t);
}

template <class T> void MyContainer<T>::removeAll()
{
    items.clear();
}

template <class T>
T& MyContainer<T>::getNext()
{
    if(isEnd() || isEmpty())
        return throw std::out_of_range("");
    return *it++;
}

template <class T>
void MyContainer<T>::isBegin()
{
    it = items.begin();
}

template <class T>
bool MyContainer<T>::isEnd()
{
    return it==items.end();
}

Если экземпляры B должны быть разделены между классом A и классом C (списки в A и C ссылаются на одни и те же объекты B), то вы можете хранить общие указатели в списках.

0 голосов
/ 11 ноября 2010
  • сначала вы выделяете
  • тогда вы "берете и кладете" куда-то (не выделяя, просто копируя указатели)
  • тогда вы освобождаете
  • тогда вы освобождаетесь. ... ждать
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...