Boost Development Guide - 4.1noncopyable

noncopyable

noncopyable allows programs to easily implement a class that prohibits copying.

noncopyable is located in the namespace boost. In order to use noncopyable components, you need to include the header file <boost/noncopyable.hpp> or <boost/utility.hpp> (the latter contains the implementation of several small tools):

#include <boost/noncopyable.hpp> //或者
#include <boost/utility.hpp> 

principle

When defining a class in C++, if the copy constructor and copy assignment operator are not explicitly defined, the compiler will automatically generate these two functions for us.

For example:

class empty_class();

For such a simple "empty" class R, the compiler will "silently" add a copy constructor and a copy assignment operator to it when processing it. The real code is similar to:

class empty_class
{
    
    
public: //构造和析构暂时忽略
   empty_class (const empty_class &){
    
    ...} //拷贝构造函数
   empty_class & operator=(const empty_class &){
    
    ...} //拷贝赋值
};

In general, this is useful, for example, it can automatically support swap(), conform to the copy semantics of the container, and can be put into a standard container for processing, but sometimes we don’t need the copy semantics of the class and hope to prohibit copying the instance of the class.

This is a very classic c++ idiom. The principle is easy to understand. You only need to privatize the copy constructor and copy assignment operator, and the handwritten code is also very simple (scoped_ptr uses this idiom), for example:

class do_not_copy
{
    
    
private:
   do_not_copy (const do_not_copy &); //私有化,声明即可,不需要实现代码
   void operator=(const do_not_copy &); //私有化,声明即可,不需要实现代码
};

But if there are a large number of such classes in the program, it is quite tedious to repeatedly write such codes, and the more codes appear, the easier it is to increase the chance of handwriting errors. While it is also possible to use macros with parameters to reduce duplication, the solution is less elegant.

usage

noncopyable provides a simple and clear solution for implementing non-copyable classes: just derive from boost::noncopyable.

Using noncopyable, the above example can be simplified to:

#include <boost/noncopyable.hpp>
class do_not_copy: boost::noncopyable
{
    
    ...};

Note that using the default private inheritance is allowed here. We can also explicitly write private or public modifiers, but the effect is the same. Therefore, writing directly in this way saves some code input, is clearer, and shows the HAS-A relationship (rather than ISA).

If someone else writes the code by mistake (probably without reading the interface document carefully), attempting to copy construct or assign do_not_copy, then it will fail the compiler's review:

do_not_copy d1; //一个不可拷贝对象
do_not_copy d2(d1); //企图拷贝构造,编译出错
do_not_copy d3; //另一个不可拷贝对象
d3 = d1; //企图拷贝赋值,编译出错

Compiling with GCC will report an error message similar to the following:

note: 'do_not_copy::do_not_copy(const do_not_copy&)'
is implicitly deleted because the default definition would be ill-formed:
class do_not_copy: boost::noncopyable
error: use of deleted function 'boost::noncopyable_ ...'

This error message clearly tells us: the class uses boost::noncopyable to disable (delete) the copy construction, and the copy constructor cannot be called.

Whenever possible, use boost::noncopyable, it expresses the intent of the class designer unambiguously, is more user-friendly, and plays well with other Boost libraries.

accomplish

class noncopyable
{
    
    
protected:
   noncopyable() {
    
    }
   ~noncopyable() {
    
    }
private:
   noncopyable (const noncopyable&); //私有化拷贝构造和拷贝赋值
   const noncopyable& operator=(const noncopyable&);
};

Therefore, when our custom class is a subclass of noncopyable, it will automatically privatize the noncopyable copy constructor of the parent class, thereby prohibiting users from accessing the copy constructor and copy assignment function from the outside.

If you use the new default and delete keywords of the C++11 standard, noncopyable can be implemented more clearly as follows:

class noncopyable
{
    
    
protected:
    noncopyable() = default; //默认的构造和析构是保护的
    ~noncopyable() = default; //使用默认实现
    //使用delete关键字禁用拷贝构造和拷贝赋值
    noncopyable(const noncopyable&) = delete;
    const noncopyable& operator=(const noncopyable&) = delete;
};

code example

#include <iostream>
using namespace std;

#include <boost/noncopyable.hpp>

//
class do_not_copy : boost::noncopyable
{
    
    };

//


int main()
{
    
    
	do_not_copy d1;
	//do_not_copy d2(d1);
	//do_not_copy d3;
	//d3 = d1;
}

Guess you like

Origin blog.csdn.net/qq_36314864/article/details/132097951