Явно удаляя деструкторы и не вызывая delete - PullRequest
6 голосов
/ 01 февраля 2012

Я читал C ++ 11 FAQ и заметил это:

class X4 {
    ~X4() = delete; // Disallow destruction
}

Это также косвенно запрещает перемещение X4. Копирование разрешено, но не рекомендуется.

Я также нашел эта цитата .

Удаление определения деструктора потребует выделения в свободном хранилище, поскольку статические и автоматические объекты неявно вызывают деструктор: `

struct C
{
    ~C()= delete; //prevent automatic and static objects
};

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

Что имеет смысл. У меня вопрос: считается ли хорошей практикой иметь синглтон с явно удаленным деструктором? Кроме того, если кто-нибудь знает о каких-либо других сценариях, в которых вы не должны звонить delete, пожалуйста, дайте мне знать.

Ответы [ 3 ]

2 голосов
/ 02 февраля 2012

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

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

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

Хотя вы могли бы «решить» эту проблему, не уничтожая объект глобальной базы данных, я не думаю, что это действительно следует называть «хорошей практикой». Это больше похоже на простой способ справиться с плохой ситуацией без перепроектирования (хотя в моем примере редизайн тоже может быть довольно простым - просто убедитесь, что либо регистратор БД, либо сама БД делает что-то полезное с сообщениями журнала когда соединение закрыто. Проглотите их или перенаправьте в другое доступное место назначения.

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

1 голос
/ 01 февраля 2012

Кроме того, если кто-либо знает о каких-либо других сценариях, в которых вы не должны вызывать команду delete, сообщите мне.

Использование пула памяти - один из сценариев, который я могу придумать.

0 голосов
/ 06 июля 2014

В одной ситуации деструктор никогда не будет вызван, даже для автоматических переменных: деструктор для анонимного объединения внутри класса X, когда пользователь пишет явный деструктор X::~X.Поскольку объединение является анонимным, просто нет способа, которым его деструктор может быть вызван X::~X (теперь он не как называет деструктор, потому что он не знает , что длявызовите деструктор).

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

Любопытно, что в этой ситуации деструктор по умолчанию X::~X вызвал бы деструктор для анонимного объединения.Однако всякий раз, когда это разрешено, это чисто формальный вопрос, и вызов деструктора не действует.Это потому, что это допустимо, только если все варианты объединения имеют тривиальные деструкторы (и, следовательно, сам союз);если у любого из них есть нетривиальный деструктор, то деструктор объединения неявно удаляется, что делает деструктор по умолчанию X неработоспособным (эффективно удаляемым).

Однако это не означает, что нельзя использоватькласс X, содержащий анонимный союз, по крайней мере, с одним членом с нетривиальным деструктором.Это просто означает, что написанный пользователем X::~X должен непосредственно уничтожить активный вариант анонимного объединения, минуя удаленный деструктор самого объединения.Это возможно при условии, что класс содержит дополнительные члены, позволяющие узнать, какой вариант активен.Аналогично, конструкторы X должны напрямую создавать не более одного варианта объединения, минуя (возможно, удаленный) конструктор анонимного объединения (если вариант не является POD, такой конструктор не должен вместо этого непосредственно присваиватьвариант объединения).На самом деле специальные функции-члены анонимного объединения являются своего рода фантомными сущностями, которые не могут быть нетривиальными, и чья единственная роль, возможно, при удалении, заключается в эффективном распространении этого удаленного статуса на соответствующую специальную функцию-член, содержащую X.

...