Деструктор в C ++ - PullRequest
0 голосов
/ 18 мая 2011

Я создал заголовочный файл с классом cmysqldb с большим количеством указателей. Моя проблема сейчас такова:

Как я могу создать деструктор, который удалит указатели, которые могут вызвать потенциальную утечку памяти?

вот код заголовка:

#ifndef CMSYQLDB_H
#define CMSYQLDB_H

#include <QMultiMap>
#include <QStringList>
#include "mysql.h"

class cmysqldb
{

public:
    cmysqldb::~cmysqldb()
    {
        const char *text,
        MYSQL *connection,
        MYSQL_RES *result,
        MYSQL_RES *fresult,
        MYSQL_FIELD *mfield
    }
    int query_state;
    int numfields;
    MYSQL mysql;
    MYSQL_ROW row;
    MYSQL_ROW fieldrow;


   ....


};


#endif // CMSYQLDB_H

это то, что вы имеете в виду ???

Ответы [ 4 ]

2 голосов
/ 18 мая 2011

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

Чтобы объявить деструктор, добавьте в объявление класса следующее:

~cmysqldb();

Обратите внимание, что если у вашего класса будут какие-либо виртуальные методы, вы должнывместо этого объявите это как:

virtual ~cmysqldb();

И в свой исходный файл добавьте:

cmysqldb::~cmysqldb()
{
    // contents of your destructor goes here.
}

Теперь, насколько точно вы освободите свои ресурсы, зависит от того, как они были распределены.Если вы использовали какую-то библиотечную функцию создания и есть свободная библиотечная функция, используйте ее.Если он был выделен с помощью malloc , тогда используйте free ;если он был выделен с помощью new , используйте delete ;если он был выделен с помощью new [] , то используйте delete [] .Кроме того, вы должны использовать классы интеллектуальных указателей, такие как boost :: scoped_ptr (std :: unique_ptr) или boost :: shared_ptr (std :: shared_ptr), где это возможно, чтобы избежать явного управленияэти ресурсы через new / delete в ваших конструкторах / деструкторах.

Еще один, очень важный момент ... всякий раз, когда у вас есть функция, которая принимает указатель, очень важно документировать семантику владения.Это принадлежит вызывающему абоненту?Передано ли право собственности?И т.д.

2 голосов
/ 18 мая 2011

Ресурсы, полученные через new, должны быть освобождены с использованием delete, а с new[] должно быть с delete[].Так просто, чтобы избежать утечек памяти.Может быть более полезным, если вы разместите более конкретный код.

Деструктор носит то же имя класса, за исключением того, что перед ним стоит символ ~.

cmysqldb :: ~cmysqldb()
{
    // deallocate the resources with the above mentioned rule 
}

class foo
{
    int var ;
    int *ptr ;

    public:

        foo()
        {
             ptr = new int ;
        }

        ~foo()
        {
             delete ptr ;
        }
};

void bar()
{

    foo obj ;

    // .....

} // <-- obj goes out of scope and it's destructor is called at this point.

foo класс имеет две переменные-члены var, ptr типа int, int* соответственно.Таким образом, байты, необходимые для хранения целого числа в var, и указатель (ptr), который может указывать на адрес целого числа, распределяется автоматически.Эти ресурсы не выделены нами.Таким образом, мы не обязаны освобождать эти ресурсы.Все идет нормально.

ptr = new int ;

new int получает ресурсы из бесплатного хранилища, в котором может храниться int, и возвращается его адрес, который хранится ptr.Теперь это приобретение ресурса из бесплатного хранилища происходит из-за операции new, определенной пользователем.Таким образом, задача пользователя - вернуть ресурсы обратно в бесплатный магазин.Итак, утверждение в деструкторе -

delete ptr ;

Получите книгу из Руководства и списка книг по С ++ Definitive C ++ , которые могут даже объяснить лучше.Также следуйте советам @Michael по использованию умных указателей, которые автоматически управляют ресурсами.

0 голосов
/ 18 мая 2011

Лучше всего было бы использовать умные указатели для хранения всех указателей на связанные объекты.C ++ будет автоматически вызывать деструкторы всех подобъектов, когда родительский объект будет уничтожен.

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

Для получения дополнительной информации посмотрите RAII (Приобретение ресурсов - инициализация).*

0 голосов
/ 18 мая 2011

Утечка памяти происходит, когда вы получаете динамическую память, используя new или new[], и не освобождаете память, используя delete или удаляете [] `.

Ваше объявление конструктора имеет тип:

cmysqldb(const char *text, MYSQL *connection, MYSQL_RES *result, 
         MYSQL_RES *fresult, MYSQL_FIELD *mfield);  

Вы должны отслеживать все динамические выделения памяти, которые вы делаете в конструкторе с new и new[], и вы должныосвободить их всех с соответствующими delete или delete[].

...