问题
Prior to C++11, I saw code like this:
class Car {
public:
Car() {}
private:
Car(const Car&);
Car& operator=(const Car&);
};
For C++11 (and later), I see code like this:
class Car {
public:
Car() {}
private:
Car(const Car&) = delete;
Car& operator=(const Car&) = delete;
};
Do they behave identically? If not, please explain.
Ref: https://ariya.io/2015/01/c-class-and-preventing-object-copy
回答1:
They are similar in most respects, but differ in some others.
Consider the following external code trying to copy objects of the class:
int main() {
Car c;
Car other{c};
}
Both of these versions will cause the above code to fail. At this point, though, the developer would look at the interface to see why. With the delete
version, it's obvious that Car
was not meant to be copied. With the private
version, (at least without a comment), it raises a doubt whether the copy constructor was perhaps placed in the private
section by accident.
Now consider member code trying to copy objects of the class:
void Car::foo() {
Car c;
Car other{c};
}
The delete
version fails like before. The private
version is a link error. This raises an even greater doubt - it's not uncommon to forget to define a method that has been declared. Perhaps this is what's happened here? The delete
version doesn't have this problem.
Edit Scott Meyers discusses this in Item 11 of Effective Modern C++ Prefer deleted functions to private undefined ones.
回答2:
=delete
will give more meaningful error messages. An error message about a deleted function tells you that it doesn't exist and no one can create an object with said constructor. Saying it is private doesn't give that information - it just says the caller cannot call it, not that no one can.
Also, a deleted constructor will not behave differently if called from within/outside the class (since private constructors can be called from within the class).
https://godbolt.org/g/06R9AQ
回答3:
Note that the two snippets you posted give exactly the same error, that is something like:
'Car(const Car&)' is private within this context
This is because you defined the member methods as private in both cases.
If you want to appreciate the differences, you should rather have public delete
d copy constructor and copy operator, that is:
class Car {
public:
Car() {}
// private: <-- this should not be here
Car(const Car&) = delete;
Car& operator=(const Car&) = delete;
};
This way, you will be informed that those member methods have been explicitly and intentionally deleted:
use of deleted function 'Car(const Car&)'
Setting them as private doesn't say explicitly I want to delete them.
As an example, it could have been done for you want to force the users of your class to use a factory method to create instances of that class.
Anyway, (no longer so) new features are not for free and using them in a way that is not the intended one won't give the expected benefits.
回答4:
Car& operator=(const Car&) = delete;
is expressing explicitly "copy assignment prohibited".
= delete;
can also be used for any function as described on Bjarne's blog:
struct Z {
// ...
Z(long long); // can initialize with an long long
Z(long) = delete; // but not anything less
};
来源:https://stackoverflow.com/questions/39888012/making-a-class-non-copyable-private-undefined-methods-vs-deleted-methods