Step 5 of 8
Non-copyable classes
For some resources, copying makes no sense at all. What would it mean to copy an open network connection, a lock on a mutex, or a handle to a unique hardware device? Two objects would both think they own it and both try to release it.
The right answer is to forbid copying. Write the copy operations and mark them = delete:
#include <iostream>
#include <type_traits>
class Connection {
public:
explicit Connection(int id) : id_(id) { std::cout << "connect " << id_ << "\n"; }
~Connection() { std::cout << "disconnect " << id_ << "\n"; }
Connection(const Connection&) = delete;
Connection& operator=(const Connection&) = delete;
int id() const { return id_; }
private:
int id_;
};
void use(const Connection& c) {
std::cout << "using " << c.id() << "\n";
}
int main() {
Connection c(7);
use(c);
std::cout << std::is_copy_constructible_v<Connection> << "\n";
}
connect 7
using 7
0
disconnect 7
Now Connection d = c; is a compile error: call to deleted constructor of 'Connection'. The mistake is caught before the program ever runs. Passing by reference (const Connection&) still works, because no copy is made.
Two copy operations
There are two copy operations to delete:
- The copy constructor
Connection(const Connection&), used forConnection d = c;. - The copy assignment operator
Connection& operator=(const Connection&), used ford = c;whendalready exists.
std::is_copy_constructible_v<T> (from <type_traits>) asks the compiler, at compile time, whether a type can be copied. It's how the tests on this step check your class.
A non-copyable type can still be made movable (able to hand over ownership) by writing move operations, which the move semantics module covers. But note that declaring the copy operations, even as = delete, stops the compiler from generating move operations for you, so Connection above can't be moved either. std::unique_ptr is the standard library's best-known type that can't be copied but can be moved.
Your turn: make Lock non-copyable. The tests check it at compile time with std::is_copy_constructible_v.
Previous: The copy problem Next: Copy assignment with copy-and-swap