如何使用抽象类指针避免内存泄漏

时间:2019-06-20 10:29:02

标签: c++ class memory abstract

假设我有一个抽象类(在下面的示例中为“ Book”)和一些派生类(在下面的示例中为“ ElectroniBook”,“ CodingBook”)。我还想保留第三类(“图书馆”)中的书籍矢量以及一些地图以查找它们。我们还假设我需要使用“ addBook”方法在其他地方创建“库”,然后在主库中进行分配。

由于Book是抽象的,所以我最终需要删除创建的“ Book”指针,并且希望在某些析构函数中进行操作。没关系,每当我尝试使用Delete时,我都会收到此错误消息

Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

,如果我尝试用shared_pointers或unique_pointers替换原始指针,我会在编译时立即收到错误消息,告诉我我正在尝试使用已被删除的指针。请注意,我正在使用C ++11。

以下是一些代码,例如:

class Book{
public:
Book(string name, int Npages);
virtual ~Book();
virtual void displayBook() = 0;
private:
string _name;
int _Npages;
}


class ElectronicBook : public Book{
public:
ElectronicBook(string name, int Npages);
~ElectronicBook();
void displayBook() {  //do something 
                    };
}

class CodingBook : public Book{
public:
CodingBook(string name, int Npages);
~CodingBook();
void displayBook() { // do something  else
                    };
}


class Library{
public :
 Library();
~Library(){
 // this doesn't work for me
// for(auto & a : _books)
//    delete a;
//  _books.clear();
// 
//for(int i=0;i<_bookmap.size();++i)
//    delete bookmap.at(i);    
};

void addCodingBook(string name, int Npages){
CodingBook* cb = new CodingBook(name, Npages);
_books.push_back(cb);
_bookmap[name] = cb;

//should I delete anything here?
};

void addEletronicBook(string name, int Npages){
ElectronicBook* eb = new ElectronicBook(name, Npages);
_books.push_back(eb);
_bookmap[name] = eb;

//should I delete anything here?
};

private :
vector<Book*> _books;
map<string, Book*> bookmap;
}


// separeted function
Library createLibrary(){

    Library L;
    while(...){
     //read books from somewhere(file, input or whatever) and 
    // addElectronicBook(...) 
    // addCodingBook(...)
    }

 return L;
}


int main(){

Library myLibrary = createLibrary();
// do something with Library
}

由于我多次“添加”新书,因此需要删除它们。我试图像我展示的那样在Library析构函数中进行此操作,但是遇到了前面提到的错误。

1 个答案:

答案 0 :(得分:3)

如果我正确理解了您的问题,那么您将释放两次相同的内存:

// for(auto & a : _books)
//    delete a;
//  _books.clear();
// 
//for(int i=0;i<_bookmap.size();++i)
//    delete bookmap.at(i); 

_booksbookmap都包含指向相同内存区域的指针,并且您将它们释放了两次。 在使用原始指针时,您必须确定谁是内存的所有者,例如_books,以及谁可以直接访问内存但不负责清理。 因此,您应该:

  1. 仅删除一次,因此仅使用两个for循环之一,例如,为参数_books

  2. 确保其他非所有权结构(在我们的示例中为bookmap)在删除后再也不会访问内存(即取消引用指针)

建议:将向量unique_ptr放入其中,以便向量成为所有者,并将原始指针放入地图中,以表明该地图未拥有。 unique_ptr将为您清理内存。如果您想确定的话,如果您有调试器,请添加一些打印语句或在析构函数中放置断点。