Нужно ли удалять в деструкторе? - PullRequest
9 голосов
/ 28 июня 2011

У меня есть следующий код, и мне интересно, нужно ли здесь delete b? Будет ли моя операционная система автоматически очищать выделенную область памяти?

class A
{
    B *b;

    A()
    {
        b = new B();
    }

    ~A() 
    {
        delete b;
    }
};

Большое спасибо.

Ответы [ 9 ]

12 голосов
/ 28 июня 2011

Да, вам нужно delete каждый объект, созданный с new , которым вы владеете .В этом самом случае это выглядит так, как будто class A владеет этим экземпляром class B и отвечает за вызов delete.

. Вам будет намного лучше использовать интеллектуальный указатель для управления экземпляром class Bпродолжительность жизни.Также обратите внимание, что вы должны либо внедрить, либо запретить оператор присваивания и конструктор копирования в class A, чтобы предотвратить поверхностное копирование объекта, что доставит вам много хлопот.

5 голосов
/ 28 июня 2011

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

Всегда полезно использовать умные указатели для объектов с динамическим покрытием. Они сделают все для вас.

  • станд :: auto_ptr
  • повышение :: shared_ptr
  • повышение :: scoped_ptr
2 голосов
/ 28 июня 2011

Если вы вызываете новый, всегда рекомендуется соответствующее удаление.

Что касается операционной системы, удаляющей вашу память ... да, это произойдет, но только после того, как завершится весь процесс (т.е. ваше приложение завершится). Только тогда вся память и другие ресурсы возвращаются ОС.

В-третьих, старайтесь использовать новый / удалять только при необходимости. В вашем сценарии вы можете просто написать

class A 
{

B b;

  A() {}

  ~A() {}

};

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

2 голосов
/ 28 июня 2011

Это, безусловно, необходимо, как вы это написали.Однако даже с delete класс в корне нарушен, поскольку он управляет ресурсом, но не следует правилу трех .

При этом почти наверняка нет причинручное управление памятью - там редко бывает.Вполне вероятно, что в качестве переменной-члена вам нужно либо просто указать объект B, либо использовать интеллектуальный указатель, например QScopedPointer:

struct A
{
    QScopedPointer<B> b;
    A() : b(new B()) { }

    // No ~A() needed; when the A object is destroyed, QScopedPointer ensures 
    // that the B object pointed to by the member 'b' is destroyed and deleted.
};

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

1 голос
/ 28 июня 2011

Управление ресурсами - это больше, чем просто освобождение памяти. Да, большинство платформ выделяют любую память, которую вы выделяете, когда процесс заканчивается, а память достаточно дешевая, что, возможно, вы не заметите некоторое время. Но как насчет файла, который b держит открытым, или мьютекса, который он разблокирует в своем деструкторе? Задолго до того, как у вас не хватит памяти, вы можете столкнуться с проблемами, если позволить вашим объектам жить дольше их полезности.

1 голос
/ 28 июня 2011

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

В большинстве современных операционных систем (определенно ОС, которые люди обычно запускают на настольных компьютерах) все, что использует процесс, будет очищено по окончании процесса, поэтому, если вы забудете delete, то память все равно будет освобождена , Однако не стоит полагаться на это.

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

1 голос
/ 28 июня 2011

Член b будет размещен в куче. Это правда, что операционная система освободит всю память, занятую кучей; однако это произойдет только один раз: при выходе из программы .

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

Таким образом, ответ в основном таков: да , вам нужно вызвать delete вручную, так как память не будет освобождена как можно скорее (хотя умные указатели помогут вам достичь чего-то подобного).

1 голос
/ 28 июня 2011

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

0 голосов
/ 28 июня 2011

1) При длительном запуске приложений могут возникать проблемы, поскольку ОС может освободить память только после прекращения работы приложения.

2) delete b; также вызывает деструктор экземпляра с указателем на Bбежать.В противном случае он никогда не запустится, так как больше нет способа добраться до него.Этот деструктор может сделать что-то важное.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...