For example, I want to declare a class but I want the client to not be able to use the copy constructor (or copy assignment operator)
Both of the following two does not allow the use of the copy constructor:
1.
class Track
{
public:
Track(){};
~Track(){};
private:
Track(const Track&){};
};
2.
class Track
{
public:
Track(){};
~Track(){};
Track(const Track&)=delete;
};
Is one of these ways "more correct" than the other or are equal? Is there any side-effect?
//Does not compile with both the above ways
int main()
{
Track l;
Track p(l);
}
In the first case, you are essentially declaring a private copy constructor and then not providing any implementation. By declaring them private, non-members cannot copy it.
In the second case, the syntax forbids a copy being made. This is C++ native.
The major difference as a programmer is readability and understanding the code. The first case is redundant, why declare the copy constructor, make it private, and not implement it. The client has to infer a lot here.
You can just use "= delete" and clearly imply what you're trying to do.
Your first solution conveys to the reader that the copy-constructor is private and is not to be used. Your second solution is only valid in C++11. Because of this, I'd say the more portable and readable implementation would be your first, using the private-property.
Making it private is the "old" way of doing it. The constructor still exists, but it is private, and can only be invoked from within another class member function.
= delete
deletes the constructor. It is not generated by the compiler, and it simply will not exist.So most likely,
= delete
is what you want. (although with the caveat that not all compilers support this syntax yet, so if portability is a concern...)Making a constructor private was basically a "hack" in the old C++, since it was the only way to prevent users from using them. The ability to
delete
special member functions was only introduced in C++11, and it's the better and more idiomatic way to say that a class cannot be copied. since it is explicit about the intention.Private constructors have other uses other than forbidding their use entirely (e.g. they may be called by static class member functions). So just making a constructor private doesn't communicate the intention very well, and the resulting error is not very clear, either.
If you are on C++11, use
delete
. The reason is that it makes the call explicit and the intent clear. You could still accidentally use a private constructor (e.g. in a restricted set of scopes), but the compiler will forbid you from ever using a deleted constructor.One issue of the private constructor is that the class and friends can still use it -- this results not in access errors but link errors, which can be hard to trace back to the callsite.
If your necessary toolchains do not support deleted constructors (
= delete
), you should not define it (as seen in your question) -- only declare it and leave it undefined, e.g.:private: \n Track(const Track&);
Declaring a copy constructor
private
still allows member functions of theTrack
class to copy-construct instances of that class, while making it deleted simply forbids copy-constructing that object.In C++11, deleting a copy constructor is the right way to express the fact that a class is non-copyable (unless of course it makes sense for you to let member functions of
Track
, or friends ofTrack
, to copy-constructTrack
objects).