2014-01-09 5 views
9

Можно ли автоматически создавать деструкторы в C++?Возможно ли автоматическое создание деструкторов в C++?

Это слишком большая нагрузка, чтобы сделать это самостоятельно. Это так сложно для компилятора для создания деструкторов? Не может ли он определить, что такое «ресурс» и отпустить его в деструкторе?

+6

Если вы хотите управлять ресурсом, это зависит от вас. Большую часть времени вам не нужно, если вы используете надлежащие возможности C++, и деструктора по умолчанию достаточно. Но представьте, что вы завернули функцию C 'fopen()' в классе C++ и должны быть закрыты в destructore. Как мог компилятор C++ знать, что он должен вызывать 'fclose()' в деструкторе? – nos

+16

слишком большая нагрузка? Похоже, вы должны использовать RAII! – Salgar

+1

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

ответ

32

Конечно, это так, и это именно то, что делает язык. Если вы не объявите деструктор, то для вас будет создан: он будет вызывать деструктор каждого элемента и базового подобъекта.

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

+6

Если вы определяете деструктор, компилятор все равно вызовет деструктор каждого элемента и базового подобъекта. –

+0

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

+4

@squelart Больше не подходит для C++ 11. Вы можете написать 'virtual ~ Foo() = default;'. – ruds

10

Невозможно точно определить. Даже если компилятор замечает, что вы выделяете ресурс в конструкторе или в какой-либо другой функции объекта, это необязательно следует, что он должен быть выпущен в деструкторе. Все зависит от того, владеет ли объект «владельцем» ресурса.

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

4

Ни C++, ни C++ 11 не имеют сборку мусора. C++ 11 вводит ряд классов управляемого указателя в памяти файл заголовка - shared_ptr, weak_ptr и unique_ptr. Они предназначены для предотвращения утечек памяти. Для пояснения см. C++ Smart Pointers учебник и Smart Pointers (Modern C++) на MSDN.

+0

Пока самый последний стандарт C++ - это 2011 год, C++ - это C++ 11, не так ли? – Prateek

5

Сложно ли компилятор генерировать деструкторы?

Речь не идет о том, что легко или сложно сделать компилятору. Речь идет о фундаментального принципа программирования C++:

Вы не должны платить за то, что вам не нужно.

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

Каждый класс нуждается в деструкторе. Вот почему компилятор автоматически пишет один для вас, если вы не делаете этого самостоятельно. Этот неявный деструктор уничтожает все члены и базовые классы в определенном порядке и определенным образом. Иногда это не то, что вы действительно хотите, но этот компилятор не может этого принять. Классический случай - это классы интеллектуальных указателей. Класс интеллектуального указателя будет иметь необработанный указатель на контролируемый объект где-нибудь, но компилятор не знает, должен ли этот указатель быть delete d - возможно, вы используете интеллектуальный указатель-счетчик-счетчик. Если вам нужен деструктор, на самом деле указатель, который вы должны написать себе.

Другой случай - с delete производными классами. Рассмотрим:

Base* p = new Derived; 
delete p; 

Если Derived имеет кучу вещей в нем, который должен быть освобожден, то вам необходимо убедиться, что, когда вы deleteDerived объект через Base указатель, деструктор Derived «s является тот, который на самом деле называется - даже несмотря на то, что компилятор не имеет возможности узнать на сайте вызова, что p фактически указывает на Derived. Чтобы выполнить эту работу, вам необходимо создать Base::~Base a virtual деструктор.

Смежные вопросы