Что я должен собирать в деструкторе C ++? - PullRequest
3 голосов
/ 31 января 2012

Я пишу деструктор C ++ (надеюсь, это правильный термин; я новичок в C ++), и я не уверен, что именно мне нужно для сборки мусора.Допустим, у меня есть 2 указателя в качестве переменных экземпляра. Нужно ли их собирать?А что, если у меня есть объект в качестве переменной экземпляра?Или указатель на объект?

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

Спасибо

Ответы [ 7 ]

11 голосов
/ 31 января 2012

Общее правило: если вы звонили new, звоните delete.Если вы позвонили new[], позвоните delete[].Если вы обращаетесь к этим указателям за пределами класса и эффективно делитесь ими, вам нужно быть осторожным с «владельцем» объекта delete, который использует общие объекты, пока они еще используются.Сборка мусора не совсем подходящий термин.Вы хотите destroy объект и free его память.Это то, что делает delete / delete[].new / new[] выделяет память и construct объект.

В C ++ нет сборщика мусора.Вы должны "вручную" справиться с этим.Это не значит, что все это надоело.Вы, вероятно, начнете использовать умные указатели , чтобы справиться с этой логикой для вас.См. этот вопрос для получения дополнительной информации.

3 голосов
/ 31 января 2012

Вы должны начать с изучения «Приобретение ресурсов - инициализация» (RAII) и умных указателей (shared_ptr и unique_ptr). Это идиома, которую вы должны знать в C ++, если вы пришли из других языков.

Обычная практика говорит, что все, что вы выделили в своем конструкторе, должно быть освобождено в вашем деструкторе (см. Другие ответы, чтобы узнать как). Событие лучше, старайтесь использовать значения как можно больше, а new - как можно меньше. C ++ любит стек, а выделение и освобождение стека происходит автоматически и дешево (без нового, без удаления). Используйте ссылки и константные ссылки вместо указателей.

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

3 голосов
/ 31 января 2012

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

Вы также должны закрыть все открытые сокеты и очистить любые другие ресурсы ОС, которыми владеет ваш класс.

Примечание: это не называется сборкой мусора.Сборка мусора - это когда этот процесс происходит автоматически, как часть времени выполнения библиотеки или языка, а не когда вы делаете это явно.

3 голосов
/ 31 января 2012

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

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

Дело не в том, какие указатели у вас есть в экземпляре класса.Вам необходимо знать, кому принадлежит (владелец является ответственным за их удаление).Если вашему объекту принадлежат эти указатели, он должен их удалить.Если он не владеет ими, то не должен.

Именно поэтому опытные программисты на C ++ избегают использования голых указателей, где это возможно.Умные указатели позволяют вам семантически выражать виды собственности на языке.Таким образом, вам не нужно отслеживать, кому что принадлежит;Вы знаете, кому он принадлежит, по типу используемого интеллектуального указателя.

2 голосов
/ 31 января 2012

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

Для массива начните с std::array и std::vector. Для объектов, читайте на умные указатели и общие указатели. Как обобщение : если вам нужно позвонить delete, delete[] или free, вы обычно идете по неверному пути.

2 голосов
/ 31 января 2012

Любая память, которую вы выделяете с помощью нового оператора, должна быть освобождена.

Вы выделяете память, выполняя:

int * p1 = new int[5];
p2 = new int;

и вы удалите его, выполнив:

delete[] p1
delete p2; 

Если вы играете с классами, вам нужно сделать то же самое в конструкторах (выделить) и деструкторах (освободить).

0 голосов
/ 31 января 2012

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

...