The generation of the implicitly-defined copy constructor is deprecated if T has a user-defined destructor or user-defined copy assignment operator.

It is not easy to remember those rules, I guess it is best to declare those five constructor explicitly.

Multiple copy constructors:

A copy constructor of class T is a non-template constructor whose first parameter is T&, const T&, volatile T&, or constvolatile T&, and either there are no other parameters, or the rest of the parameters all have default values.

So it is totally legal to have multiple copy constructors with different signatures

A(const A&) could be used for both cost or non-const parameters, but not the other way around.

Notes: const applies to the thing left of it. If there is nothing on the left then it applies to the thing right of it.

Use f(X) if you need to take the ownership of the object passed. The caller of your function can just do f( std::move(something)) or f(something) when appropriate.

Use f(X&) if you need to modify the passed object.

Use f(X&&) if you need to own the passed object.

Multiple Move constructors:

A move constructor of class T is a non-template constructor whose first parameter is T&&, const T&&, volatile T&&, or constvolatile T&&, and either there are no other parameters, or the rest of the parameters all have default values.

but const T&& in move constructor does not make much sense, the reason are:

The rvalue references don’t make sense in their const forms because you want to modify them (you want to “move” them ). Objects created as const in C++ are in read-only memory, from which grabbing/modifying internal resources won’t be possible.