Explicitly deletes destructors and does not cause deletion

I read the C ++ 11 FAQ and noticed this:

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

It also implicitly disallows the movement of the X4. Copying is allowed but not recommended.

I also found this quote .

Removing the destructor definition will require allocation in free storage, since static and automatic objects implicitly invoke the destructor: `

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

However, this method is less useful than it might seem, since it also prevents the removal of expressions. Singleton objects can use it, however.

It makes sense. My question is: is it considered good practice to have a Singleton with a clearly deleted destructor? Also, if anyone knows about any other scenario, you should not call delete , please let me know.

+6
source share
3 answers

Pragmatically, sometimes you may find yourself in a situation where it is unsafe to destroy objects of a certain type. This way you remove the destructor so that no one tries.

In the case of Singleton, where there will only ever be one instance of a type, an inability to destroy it can be less harmful than if many instances were not loaded.

One of the problems with Singletons (or any other globally accessible object) is that you may lose control of dependencies on them. Then it is difficult to develop a secure destruction order - if the global database object is registered with the global registration object that you successfully closed, but, optionally, the global journal object logs it in the database through the global database object, then you have a problem.

Although you can "solve" this problem without destroying the global database object, I don’t think it really should be called "good practice." This seems like an easy way to deal with a bad situation without having to re-develop it (although in my example the redesign can be quite simple) - just make sure that either the database log or the database itself does something useful with log messages when the connection is closed, swallow them or redirect to another available destination).

It is possible that there are “good” projects in which a particular type of object cannot be destroyed, but this is not the usual way to develop C ++ classes.

+2
source

In addition, if anyone knows of any other case scenarios, you should not call delete, please let me know.

Using a memory pool is one of the possible scenarios.

+1
source

There is one situation where the destructor will never be called, even for automatic variables: a destructor for anonymous union inside the class X , when the user destructor X::~X written by the user. Since the union is anonymous, there is simply no way that its destructor can be called X::~X (now it’s not the same as calling the destructor because it does not know what to call the destructor).

By the way, in this situation, the user cannot declare the removal of the union destructor (again, due to the lack of a name), but it can be implicitly deleted.

Curiously, in this situation, the default destructor X::~X would name the destructor for anonymous union. However, when allowed, this is a purely formal matter, and calling the destructor has no effect. This is due to the fact that this is allowed only if all union options have trivial destructors (and, therefore, the union itself); if any of them has a non-trivial destructor, the union destructor is implicitly deleted, which makes the default destructor X inoperative (effectively deleted).

However, this does not mean that you cannot use class X containing an anonymous union with at least one member with a non-trivial destructor. It simply means that the user-written X::~X should directly destroy the active variant of the anonymous union, bypassing the remote destructor of the union itself. This is possible if the class contains additional elements that let you know which option is active. Similarly, X constructors must directly build at most one join option, bypassing the (possibly remote) anonymous join constructor (unless the option is a POD, such a constructor should not directly assign the join option instead), In fact, the special member functions of the anonymous unions are a kind of phantom entities that cannot be nontrivial and whose only role, being possibly removed, is to effectively extend this remote status to the corresponding special nktsiyu member containing X .

0
source

Source: https://habr.com/ru/post/907370/


All Articles