With explicitly removed member functions in C ++ 11, is it worth it to inherit from an unprepared base class?

With explicitly removed member functions in C ++ 11, is it worth it to inherit from an unprepared base class?

I am talking about a trick in which you privately inherit a base class that has a private or remote copy instance and copy destination (e.g. boost::noncopyable ).

Are the benefits in this question available for C ++ 11?




I don’t understand why some people claim that it is easier to make the class not copied in C ++ 11.

In C ++ 03:

 private: MyClass(const MyClass&) {} MyClass& operator=(const MyClass&) {} 

In C ++ 11:

 MyClass(const MyClass&) = delete; MyClass& operator=(const MyClass&) = delete; 



EDIT:

As many people have pointed out, it was a mistake to provide empty bodies (for example, {}) for the private copy constructor and copy assignment operator, since this would allow the class itself to call these operators without any errors. At first I started not to add {}, but I ran into some linker problems that made me add {} for some silly reason (I don’t remember the circumstances). I know that I know better. :-)

+57
c ++ c ++ 11 noncopyable
Feb 27 2018-12-12T00:
source share
5 answers

Well it:

 private: MyClass(const MyClass&) {} MyClass& operator=(const MyClass&) {} 

Still technically allowing MyClass copied by members and friends. Of course, these types and functions are theoretically under your control, but the class can still be copied. At least with boost::noncopyable and = delete no one can copy the class.




I don’t understand why some people claim that it is easier to make the class not copied in C ++ 11.

It is not as "easier" as "more easily digestible."

Consider this:

 class MyClass { private: MyClass(const MyClass&) {} MyClass& operator=(const MyClass&) {} }; 

If you are a C ++ programmer who has read the C ++ introductory text but is not very prone to idiomatic C ++ (i.e. many C ++ programmers), this is ... confusing. It declares copy constructors and copy assignment operators, but they are empty. So why announce them at all? Yes, they are private , but this only raises more questions: why make them private?

To understand why this prevents copying, you must understand that by declaring them confidential, you do so so that no members / friends can copy it. This is not immediately clear to beginners. This is also an error message that they will receive when they try to copy it.

Now compare it with the C ++ 11 version:

 class MyClass { public: MyClass(const MyClass&) = delete; MyClass& operator=(const MyClass&) = delete; }; 

What does it take to understand that this class cannot be copied? No more than understanding what the syntax = delete means. Any book explaining C ++ 11 syntax rules will tell you exactly what it does. The effect of this code is obvious to an inexperienced C ++ user.

What is good about this idiom is that it becomes an idiom, because it is the clearest, most obvious way of saying exactly what you mean.

Even boost::noncopyable requires a little thought. Yes, it is called “non-copyable,” so it’s self-documenting. But if you have never seen this, this raises questions. Why are you extracting from something that cannot be copied? Why do error messages talk about boost::noncopyable copy constructor? Etc. Again, understanding an idiom requires more mental effort.

+75
Feb 27 '12 at 1:05
source share

The first thing, as others preceding me indicate, you made a mistake in the idiom, declare it closed and do not define:

 class noncopyable { noncopyable( noncopyable const & ); noncopyable& operator=( noncopyable const & ); }; 

If the return type operator= can be basically anything. At the moment, if you are reading this code in the header, what does it really mean? Can it be copied only by friends or can it not be copied ever? Please note that if you give a definition, as in your example, it states that I can only be copied inside the class and friends, this lack of a definition that translates this, I can not copy. But the lack of a definition in the header is not synonymous with the lack of a definition everywhere, as it can be defined in the cpp file.

Here, inheriting from a type called noncopyable makes it clear that the goal is to avoid copying, just as if you had manually written the code above, you should document with a comment in a line that the intent disables copies.

C ++ 11 does not change anything, it just makes the documentation explicit in code. On the same line where you declare the copy constructor as remote, you are documented that you want to completely disable it.

As a final comment, the C ++ 11 function is not only that it can write noncopyable with less code or better, but rather because the compiler forbids generating code that you do not want to generate. This is just one use of this feature.

+24
Feb 27 '12 at 1:26
source share

In addition to those that others have raised ...

Having a private copy constructor and a copy assignment operator that you do not define does not allow anyone to create copies. However, if a member function or a friend function tries to create a copy, they will receive a link time error. If they try to do this when you explicitly remove these functions, they will get a compile-time error.

I always make my mistakes as soon as possible. Runtime errors are executed at the point of the error, not later (so make a mistake when you change the variable, and not when you read it). Make all run-time errors in link-time errors, so the code will never be erroneous. Make compile-time errors at compile time to speed up development and get some more useful error messages.

+10
Aug 13 '12 at 1:00
source share

This is more readable and allows the compiler to give better errors.

"Remote" is more understandable to the reader, especially if he is viewing a class. Similarly, the compiler can tell you that you are trying to copy a non-copyable type, instead of giving you a general problem with trying to access a private member.

But actually it’s just a convenient feature.

+5
Feb 27 2018-12-12T00:
source share

People here recommend declaring member functions without defining them. I would like to note that this approach is not portable. Some compilers / linkers require that, when declaring a member function, you must also define it, even if it is not used. If you use only VC ++, GCC, clang, then you can avoid this, but if you are trying to write really portable code, then some other compilers (for example, Green Hills) will not work.

+2
Jan 07 '14 at 23:04
source share



All Articles