Beyond the C ++ standard library: An Introduction to boost-library 3.4 noncopyable

Source: Internet
Author: User
Noncopyable

Header file: "Boost/utility. HPP"

Generally, compilers are good friends of programmers, but they are not always. One of its advantages is that it will automatically provide us with a copy constructor and a value assignment operator, if we decide not to do it ourselves. This may also lead to unpleasant surprises if the class itself does not want to be copied (or assigned a value ). In this case, we need to explicitly tell the users of this class that the replication structure and assignment are forbidden. I am not talking about comments in the code, but about prohibiting access to the copy constructor and the value assignment operator. Fortunately, when a class has a base class or member function that cannot be copied or assigned values, the copy constructor and value assignment operator generated by the compiler cannot be used.Boost: noncopyableThe principle is to prohibit access to its copy constructor and value assignment operator, and then use it as the base class.

Usage

To useBoost: noncopyable, You need to generate non-replicable classes from its private. Public inheritance is acceptable, but this is a bad habit. Public inheritance means a IS-A (representing a derived class IS-A base class) relation for the person who reads the class declaration, but indicates a class IS-ANoncopyableIt seems a bit incorrect. ToNoncopyableTo be derived, it must contain"Boost/utility. HPP".

#include "boost/utility.hpp"

class please_dont_make_copies : boost::noncopyable {};

int main() {
please_dont_make_copies d1;
please_dont_make_copies d2(d1);
please_dont_make_copies d3;
d3=d1;
}

This example cannot be compiled. BecauseNoncopyableThe replication constructor of is private, soD2An attempt to copy the constructor fails. Similarly, becauseNoncopyableThe value assignment operator is private, soD1AssignedD3Will also fail. The compiler will give output similar to the following:

noncopyable.hpp: In copy constructor
' please_dont_make_copies::please_dont_make_copies (const please_dont_make_copies&)':
boost/noncopyable.hpp:27: error: '
boost::noncopyable::noncopyable(const boost::noncopyable&)' is
private
noncopyable.cpp:8: error: within this context
boost/noncopyable.hpp: In member function 'please_dont_make_copies&
please_dont_make_copies::operator=(const please_dont_make_copies&)':
boost/noncopyable.hpp:28: error: 'const boost::noncopyable&
boost::noncopyable::operator=(const boost::noncopyable&)' is private
noncopyable.cpp:10: error: within this context

In the next section, we will test how this works. It is clear fromNoncopyableCopying and assigning values are prohibited. This can also be achieved by defining the copy constructor and the value assignment operator as private. Let's take a look.

Make the class unable to be copied

Let's look at the class again.Please_dont_make_copiesFor some reason, it cannot be copied.

class please_dont_make_copies {
public:
void do_stuff() {
std::cout <<
"Dear client, would you please refrain from copying me?";
}
};

Since the compiler generates a copy constructor and a value assignment operator, copying and assigning values of classes cannot be disabled.

please_dont_make_copies p1;
please_dont_make_copies p2(p1);
please_dont_make_copies p3;
p3=p2;

The solution is to declare the copy constructor and the value assignment operator as private or protected, and add a default constructor (because the compiler no longer automatically generates it ).

class please_dont_make_copies {
public:
please_dont_make_copies() {}

void do_stuff() {
std::cout <<
"Dear client, would you please refrain from copying me?";
}
private:
please_dont_make_copies(const please_dont_make_copies&);
please_dont_make_copies& operator=
(const please_dont_make_copies&);
};

This works well, but it cannot be clearly told immediatelyPlease_dont_make_copiesIt cannot be copied. Next, let's changeNoncopyableThen, how can we make the class more clear to indicate that it cannot be copied and can also be typed with fewer words.

Use noncopyable

ClassBoost: noncopyableIt is specified to be used as a private base class, which can effectively disable the copy construction and value assignment operations. Use the previous example to see how to useNoncopyableWhat is the post code like:

#include "boost/utility.hpp"

class please_dont_make_copies : boost::noncopyable {
public:
void do_stuff() {
std::cout << "Dear client, you just cannot copy me!";
}
};

You do not need to declare a copy constructor or a value assignment operator. Because we are fromNoncopyableThe compiler will not generate them any more, so that copying and assigning values are prohibited. Conciseness can bring clarity, especially basic and clear concepts like this. For users who read this code, they immediately know that this class cannot be copied or assigned values, becauseBoost: noncopyableIt appears at the beginning of the class definition. The last note is: Do you still remember that the default access control of the class is private? This means that the inheritance is private by default. You can also write it like this to better clarify the fact:

class please_dont_make_copies : private boost::noncopyable {

This depends entirely on the audience; Some programmers consider this excess information to be annoying and distracting, while others accept this clarity. It is up to you to decide which method is suitable for your class and your programmers. Which method is used?NoncopyableThe methods for copying constructors and value assignment operators are clearer than those for "Forgetting", and they are clearer than private declarations.

Remember the Big Three

As we can see,NoncopyableIt provides a convenient way to prohibit the copying and assignment of classes. But when do we need to do this? Under what circumstances do we need to customize the copy constructor or value assignment operator? There is a general answer to this question, which is almost always the right answer: whenever you need to define a destructor, a copy constructor, or any of the three value assignment operators, you also need to define the other two[5]. The interaction between the three is very important. One of them exists, and others usually have. Let's assume that one of your classes has a member named pointer. You have defined a destructor to release the space correctly, but you have not defined a copy constructor or a value assignment operator. This means there are at least two potential risks in your code and they are easily triggered.

[5] The law is called the Big Three and comes from C ++ FAQs (for details, see [2]).

class full_of_errors {
int* value_;
public:
full_of_errors() {
value_=new int(13);
}

~full_of_errors() {
delete value_;
}
};

When using this class, if you ignore the copy constructor and value assignment operator generated by the compiler for this class, at least three errors may occur.

full_of_errors f1;
full_of_errors f2(f1);
full_of_errors f3=f2;
full_of_errors f4;
f4=f3;

Note that the second and third rows are two equivalent methods that call the copy constructor. They all call the generated copy constructor, although the syntax is different. The last error is in the last row. The value assignment operator makes the same pointer contain at least twoFull_of_errorsThe instance is deleted. The correct method is that we need our own copy constructor and value assignment operator, because we have defined our own destructor. The following are the correct methods:

  class not_full_of_errors {
int* value_;
public:
not_full_of_errors() {
value_=new int(13);
}

not_full_of_errors(const not_full_of_errors& other) :
value_(new int(*other.value_)) {}

not_full_of_errors& operator=
(const not_full_of_errors& other) {
*value_=*other.value_;
return *this;
}

~not_full_of_errors() {
delete value_;
}
};

Therefore, at any time, the Big Three of a class: copying constructor, (virtual) destructor, and value assignment operators, any of which is manually defined, you must carefully consider the remaining two before deciding whether to define them. Also, if you do not want to copy, remember to useBoost: noncopyable!

Summary

There are many types that require prohibit copying and assigning values. However, we often ignore declaring these types of copy constructor and value assignment operator as private, and pass the responsibility to the class users. Even if you use a private copy constructor and a value assignment operator to ensure that they are not copied or assigned values, it is not clear to the user. Of course, the compiler will be a friendly reminder to those who are trying to do this, but the error is not clear where it comes from. It is better for us to do this clearly.NoncopyableDerivation is a clear statement. You can immediately see the type declaration at a glance. During compilation, the error message always contains the name noncopyable. It also saves some typing, which is a key factor for some people.

UseNoncopyable:

  • Copying and assigning values of types are not allowed.

  • Prohibit duplication and assignment as much as possible

 

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.