Why does destructor disable generation of implicit move methods?

move constructor in c++ geeksforgeeks
move assignment operator
move constructor vs copy constructor
c default move constructor
when is move constructor called
rule of five c++
c move constructor implementation
move constructor geeksforgeeks

I was trying to understand what the rule of zero says by reading this blog. IMO, it says if you declare your own destructor then don't forget to make the move constructor and move assignment as default.

Example:

class Widget {
public:
  ~Widget();         // temporary destructor
  ...                // no copy or move functions
};

"The addition of the destructor has the side effect of disabling generation of the move functions, but because Widget is copyable, all the code that used to generate moves will now generate copies. In other words, adding a destructor to the class has caused presumably-efficient moves to be silently replaced with presumably-less-efficient copies".

The above text by Scott Meyers, inside the quotes raise some questions in my mind:

  • Why declaring destructor hides the move semantics?
  • Is declaring/definig destructor only hides the move semantics or copy constructor and copy assignment as well hides the move semantics?

"The Rule of Zero" is in fact about something else than what special member functions are generated and when. It is about a certain attitude to class design. It encourages you to answer a question:

Does my class manage resources?

If so, each resource should be moved to its dedicated class, so that your classes only manage resources (and do nothing else) or only accumulate other classes and/or perform same logical tasks (but do not manage resources).

It is a special case of a more general Single Responsibility Principle.

When you apply it, you will immediately see that for resource-managing classes you will have to define manually move constructor, move assignment and destructor (rarely will you need the copy operations). And for the non-resource classes, you do not need to (and in fact you probably shouldn't) declare any of: move ctor/assignment, copy ctor/assignment, destructor.

Hence the "zero" in the name: when you separate classes to resource-managing and others, in the "others" you need to provide zero special member functions (they will be correctly auto-generated.

There are rules in C++ what definition (of a special member function) inhibits what other definitions, but they only distract you from understanding the core of the Rule of Zero.

For more information, see:

  1. https://akrzemi1.wordpress.com/2015/09/08/special-member-functions/
  2. https://akrzemi1.wordpress.com/2015/09/11/declaring-the-move-constructor/

Why destructor disabling the generation of implicit move functions?, Inspired by the post Why does destructor disable generation of implicit move methods?, I was wondering if the same is true for the default virtual destructor, e.g.  It is a special case of a more general Single Responsibility Principle. When you apply it, you will immediately see that for resource-managing classes you will have to define manually move constructor, move assignment and destructor (rarely will you need the copy operations).

Almost always, if you have a destructor (that "does something"), you should follow the "rule of three", which then becomes "rule of five" if you want move semantics.

If your destructor is empty, then it's not needed. So the implication is that a non-empty destructor (because you wouldn't have one if it's not needed!), then you also need to do the same thing in copy and assignment operations, and presumably, move construction and move assignment will need to "do something", and not just transfer the actual content across.

Of course, there may be cases where this is not true, but the compiler takes the approach of "let's only apply the automatically generated move functions if the destructor is empty", because that is the "safe" approach.

Does a default virtual destructor prevent compiler-generated move , If no user-defined move constructors are provided for there are no user-​declared destructors; the generation of the implicitly declared move constructor with the keyword default . 20 Why does destructor disable generation of implicit move methods? 12 Is __del__ really a destructor? 1 The atime of a NFS directory does not get updated Sep 16 '16.

Move constructors, The implicitly-defined special member functions are typically incorrect if the Classes that have custom destructors, copy/move constructors or  By defining the destructor non-inline, we can make sure that the memory is allocated and freed using the same runtime. The second case has to do with interface stability. Switching from a compiler-provided inline definition to a user-provided non-inline one changes the binary interface of a class.

The rule of three/five/zero, Declaring a move operation (construction or assignment) in a class causes (​The copy operations are disabled by deleting them—see Item 11). have to play by the C++11 rules for special member function generation. any of a copy constructor, copy assignment operator, or destructor, you should declare all three​. Typical declaration of a move constructor. Forcing a move constructor to be generated by the compiler. Avoiding implicit move constructor. The move constructor is typically called when an object is initialized (by direct-initialization or copy-initialization) from rvalue (xvalue or prvalue) (until C++17) xvalue (since C++17) of the same type, including

Effective Modern C++: 42 Specific Ways to Improve Your Use of , Explicitly defaulted function declaration is a new form of function declaration that is special member function (default constructor, copy constructor, destructor etc​), or has no Any member function whose usage has been disabled by using the '=delete' It is very important to note that A deleted function is implicitly inline. 24 Why adding `const` makes the universal reference as rvalue 20 Why does destructor disable generation of implicit move methods? 12 Is __del__ really a destructor?

Explicitly Defaulted and Deleted Functions in C++ 11, This document describes the upcoming Nim runtime which does not use classical GC algorithms anymore but is based on destructors and move semantics. object type T (T can also be a distinct type) that are called implicitly by the compiler. The .nosinks pragma can be used to disable this inference for a single routine: A destructor is a member function that is invoked automatically when the object goes out of scope or is explicitly destroyed by a call to delete. A destructor has the same name as the class, preceded by a tilde (~). For example, the destructor for class String is declared: ~String().

Nim Destructors and Move Semantics, 1 Introduction; 2 Constructor/Destructor Errors; 3 Virtual Method Out-of-lining that have inlined/implicitly declared constructors/destructors, or are templates. However, specifying either a copy constructor or a destructor prevents the compiler from generating a move constructor. Just remove the redundant specifier. Typical declaration of a move assignment operator. Forcing a move assignment operator to be generated by the compiler. Avoiding implicit move assignment. The move assignment operator is called whenever it is selected by overload resolution, e.g. when an object appears on the left-hand side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.

Comments
  • The rationale behind this rule was that if your code has a custom destructor, it's probably because a resource needs to be freed; and if a resource needs to be freed then the default implementation of move may leave the source object in a bogus state.
  • It is not clear what "Is declaring/definig destructor only hides the move semantics or copy constructor and copy assignment as well hides the move semantics?" is asking.
  • The link mentioned in the question is not functional.
  • Hi Pete many thanks for your response, from what you are saying, the compiler will hide the implicit move if we explicitly define the Dtor(safe approach)...for what safety purpose compiler does the hiding... i read the copy operation cost high when compare to move... is the hiding happen though we define the move explicitly(i don't think so).
  • So, the general idea is that "it is safe to move something if it doesn't have a destructor". A destructor implies that destroying the object requires some special action (deleting something, counting a reference count down, etc). In move semantics, this is done by "swapping" the object from one side to another, rather than making a a copy. Of course, how this plays with "whatever you need to do in the destructor" is impossible for the compiler to actually know (unless it understands what the effect of the destructor is, and it doens't take much before that is impossible to know!)
  • I think OP is asking for the rationale behind these rules.
  • Many thanks 101010, Under what basis the hiding happens is there any rule like R0/R3/R5 or it is up to the compiler.
  • No these are standard rules all compilers follow them.
  • Nice answer, thank you so much.