Default Move Constructor/Assignment and Deleted Copy Constructor/Assignment

Default move constructor/assignment and deleted copy constructor/assignment

user-declared means either either user-provided (defined by the user), explicitly defaulted (= default) or explicitly deleted (= delete) in contrast with implicitly defaulted / deleted (such as your move constructor).

So in your case, yes the move constructor is implicitly deleted because the copy-constructor is explicitly deleted (and thus user-declared).

However, in that particular case, how would deleted copy constructor/assignment mess default move constructor/assignment?

It would not, but the standard does not make the difference between this case and a complicated one.

The shortest answer is that having an implicitly defined move-constructor with an explicitly deleted copy-constructor might be dangerous in some cases, the same when you have a user-defined destructor and no user-defined copy-constructor (see rule of three/five/zero). Now, you can argue that a user-defined destructor does not delete the copy-constructor, but this is simply a flaw in the language which cannot be removed because it would break a lot of old (bad) program. To quote Bjarne Stroustrup:

In an ideal world, I think we would decide on “no generation” as the default and provide a really simple notation for “give me all the usual operations.” [...] Also, a “no default operations” policy leads to compile time errors (which we should have an easy way to fix), whereas a generate operations by default policy leads to problems that cannot be detected until run time.

You can read more about this in N3174=10-0164.

Note that most people follow the rule of three/five/zero, and in my opinion you should. By implicitly deleting the default move-constructor, the standard is "protecting" you from mistakes and should have protected you a long time before by deleting copy-constructor in some cases (see Bjarne's paper).

Further reading if you are interested:

  • Enforcing the Rule of Zero
  • N3153 - Implicit Move Must Go
  • N3174
  • N3201

I think this question has practical importance because manual generation and esp. maintenance of such default functions is error prone, while at the same time, the (righteous) increase of the use of classes such as std::unique_ptr as class members made non-copyable classes much more common beasts than they used to be.

Marking the move constructor as explicitly defaulted will solve this problem:

class Foo {
public:
Foo() = default;
Foo(Foo const &) = delete;
Foo(Foo&&) = default;
};

You get a non-copyable object with a default move constructor, and in my opinion these explicit declarations are better than implicit ones (e.g. by only declaring the move constructor as default without deleting the copy-constructor).

Explicitly defaulted copy/move assignment operators implicitly deleted because field has no copy/move operators. C++

This data member

 const string theSeparators; 

is defined with the qualifier const. So it can not be reassigned after its initialization in a constructor.

Thus the compiler defined the copy and move assignment operators as deleted.

You can just remove the qualifier const for this data member.

Or if to keep the qualifier const for the data member then you have to use mem-initialing lists in constructors like for example

Dictionary::Dictionary(const string& filename, const string& separators = "\t\n")
: filename( filename ), theSeparators( separators )
{
//...
}

But in this case the copy and move assignment operators will be still deleted.

Why should someone create a default move constructor but delete the move assignment operator?

What this means is that, once an object is created, some aspect of its value cannot later be changed. You can move from it of course, but once that's done, you can't move back to it.

Consider a unique_ptr that had this design. Such a pointer would allow you to transfer ownership, but only to a newly constructed unique_ptr. So basically, if you create a unique_ptr, that pointer object instance will either be managing that specific object, or it will manage nothing, because you moved from it earlier. It will never be managing a different object.

Does deleting the copy constructor also deletes default copy/move operators?

Check out the lists on when such functions are implicitly deleted and when not. So the short answer to your question without repeating what is written in the documentary:

Is there any purpose of also deleting the move constructor and/or the move/copy assignment operators [...]?

Yes, there certainly is. Even if it is just emphasizing more strongly in a redundant way that a particular operation is not permitted, so it may make the interface of your code more expressive.

Has it been established if move/copy constructor/assignment are deleted or not declared in C++17?

According to N4659 (almost C++17 standard), they are still defined as defaulted but the behavior is (still) deprecated.

  • For the copy constructor, see [class.copy.ctor]/6:

If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy constructor is defined as deleted; otherwise, it is defined as defaulted. The latter case is deprecated if the class has a user-declared copy assignment operator or a user-declared destructor.

  • For the copy assignment, see [class.copy.assign]/2:

If the class definition does not explicitly declare a copy assignment operator, one is declared implicitly. If the class definition declares a move constructor or move assignment operator, the implicitly declared copy assignment operator is defined as deleted; otherwise, it is defined as defaulted. The latter case is deprecated if the class has a user-declared copy constructor or a user-declared destructor.

Is deleting copy and move constructors/assignment operators in base class enough?

You cannot prevent a child class from defining its own copy/move constructor. That said, it will prevent it "out of the box", meaning if you do not provide one, or use a inline default constructor, it will also be marked as deleted. The reason you get a error here when you try to just define the constructor as default is because you are not allowed to do that in an out of line definition when a member or base has implicitly deleted it. Had you used

class DerivedClass : public BaseClass {
public:
DerivedClass(const DerivedClass &) = default;
bool doSomething() override;
};

then the code would compile, and you would only get an error if you actually try to call the copy constructor. This works because an inline implicit default is allowed even when a member or base implicitly deletes it and the end result is the constructor is implicitly deleted.

default copy move constructor efficiency different

what is the difference between default copy constructor and default move constructor?

A default copy constructor does memberwise copy of the data members while a default move constructor does memberwise move of the data members. That is, the default move constructor steal resources instead of copying them from the passed argument.



Related Topics



Leave a reply



Submit