You have almost certainly encountered certain situations, where a class owns some resources that must not be copied for technical reasons:
class descriptor_owner { void* descriptor_; public: explicit descriptor_owner(const char* params); ~descriptor_owner() { system_api_free_descriptor(descriptor_); } };
The C++ compiler in the preceding example generates a copy constructor and an assignment operator, so the potential user of the descriptor_owner
class will be able to create the following awful things:
void i_am_bad() { descriptor_owner d1("O_o"); descriptor_owner d2("^_^"); // Descriptor of d2 was not correctly freed d2 = d1; // destructor of d2 will free the descriptor // destructor of d1 will try to free already freed descriptor }
To avoid such situations, the boost::noncopyable
class was invented. If you derive your own class from it, the copy constructor and assignment operator won't be generated by the C++ compiler:
#include <boost/noncopyable.hpp> class descriptor_owner_fixed : private boost::noncopyable { // ...
Now, the user won't be able to do bad things:
void i_am_good() { descriptor_owner_fixed d1("O_o"); descriptor_owner_fixed d2("^_^"); // Won't compile d2 = d1; // Won't compile either descriptor_owner_fixed d3(d1); }
A refined reader will note that we can achieve exactly the same result by:
- Making a copy constructor and an assignment operator of
descriptor_owning_fixed
private - Defining them without actual implementation
- Explicitly deleting them using C++11 syntax
= delete;
Yes, you are correct. Depending on the abilities of your compiler, boost::noncopyable
class chooses the best way to make the class noncopyable.
boost::noncopyable
also serves as a good documentation for your class. It never raises questions such as "Is the copy constructor body defined elsewhere?" or "Does it have a nonstandard copy constructor (with a non-const referenced parameter)?"
- The Making a noncopyable, but movable class recipe will give you ideas on how to allow unique owning of a resource in C++03 by moving it
- You may find a lot of helpful functions and classes in the
Boost.Core
library's official documentation at http://boost.org/libs/core - The Initializing a base class by the member of derived recipe in Chapter 2, Managing Resources
- The Using C++11 move emulation recipe