Как удалить вектор, который содержит другие векторы? - PullRequest
0 голосов
/ 22 сентября 2018

У меня есть этот код заголовка

    class BaseFile {
private:
    std::string name;

public:
    BaseFile(string name);
    string getName() const;
    void setName(string newName);
    virtual int getSize() = 0;

};

class File : public BaseFile {
private:
    int size;

public:
    File(string name, int size); // Constructor
    int getSize(); // Return the size of the file

};

class Directory : public BaseFile {
private:
    vector<BaseFile*> children;
    Directory *parent;

public:
    Directory(string name, Directory *parent); // Constructor
    virtual ~Directory(); //destructor
    Directory *getParent() const; // Return a pointer to the parent of this directory
    void setParent(Directory *newParent); // Change the parent of this directory
    void addFile(BaseFile* file); // Add the file to children
    void removeFile(string name); // Remove the file with the specified name from children
    void removeFile(BaseFile* file); // Remove the file from children
    void sortByName(); // Sort children by name alphabetically (not recursively)
    void sortBySize(); // Sort children by size (not recursively)
    vector<BaseFile*> getChildren(); // Return children
    int getSize(); // Return the size of the directory (recursively)
    string getAbsolutePath();  //Return the path from the root to this
};

Я реализовал все методы и деструктор

Directory::~Directory() {
for (int i = 0; i < children.size(); i++){
    BaseFile *ptr = children[i];
    delete ptr;
}
children.clear();
delete parent;
parent = nullptr;
}

и в своем основном я хочу протестировать создание каталогов внутри каталога, например:

int main(int , char **) {
//Environment env;
//env.start();

Directory *d = new Directory("test", nullptr);
Directory *d1 = new Directory("test2" , d);
File *f = new File("test" , 100);

d1->addFile(f);
d->addFile(d1);
delete d;

return 0;
}

при запуске

valgrind --leak-check=full --show-reachable=yes Assingment1

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

==20161== HEAP SUMMARY:
==20161==     in use at exit: 56 bytes in 2 blocks
==20161==   total heap usage: 6 allocs, 4 frees, 72,912 bytes allocated
==20161== 
==20161== 48 bytes in 1 blocks are indirectly lost in loss record 1 of 2
==20161==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20161==    by 0x10955D: main (Main.cpp:16)
==20161== 
==20161== 56 (8 direct, 48 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
==20161==    at 0x4C3017F: operator new(unsigned long) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==20161==    by 0x10D5E9: __gnu_cxx::new_allocator<BaseFile*>::allocate(unsigned long, void const*) (new_allocator.h:111)
==20161==    by 0x10D3F4: std::allocator_traits<std::allocator<BaseFile*> >::allocate(std::allocator<BaseFile*>&, unsigned long) (alloc_traits.h:436)
==20161==    by 0x10D0BF: std::_Vector_base<BaseFile*, std::allocator<BaseFile*> >::_M_allocate(unsigned long) (stl_vector.h:172)
==20161==    by 0x10C8E5: void std::vector<BaseFile*, std::allocator<BaseFile*> >::_M_realloc_insert<BaseFile* const&>(__gnu_cxx::__normal_iterator<BaseFile**, std::vector<BaseFile*, std::allocator<BaseFile*> > >, BaseFile* const&) (vector.tcc:406)
==20161==    by 0x10C335: std::vector<BaseFile*, std::allocator<BaseFile*> >::push_back(BaseFile* const&) (stl_vector.h:948)
==20161==    by 0x10999E: Directory::addFile(BaseFile*) (Files.cpp:42)
==20161==    by 0x10959F: main (Main.cpp:18)
==20161== 
==20161== LEAK SUMMARY:
==20161==    definitely lost: 8 bytes in 1 blocks
==20161==    indirectly lost: 48 bytes in 1 blocks
==20161==      possibly lost: 0 bytes in 0 blocks
==20161==    still reachable: 0 bytes in 0 blocks
==20161==         suppressed: 0 bytes in 0 blocks
==20161== 
==20161== For counts of detected and suppressed errors, rerun with: -v
==20161== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

есть ли лучший способ написать деструктор, чтобы он удалил все файлы в векторе?

1 Ответ

0 голосов
/ 22 сентября 2018

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

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

Если вы хотите улучшить обработку указателей, есть хороший способ сделать это, доступный из C ++ 11 и далее, под названием smart pointers .Вместо необработанного указателя, такого как Directory*, вы можете использовать, например, std::shared_ptr<Directory>, который перегружен operator-> и operator*, поэтому он ведет себя так же, как указатель в вашем коде.

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

Если вы впервые слышите об интеллектуальных указателяхЗнайте, что существует много типов указателей, подходящих для различных схем доступа и владения.Для получения дополнительной информации ознакомьтесь с введением и документами заголовка <memory> .

...