Clever Geek Handbook
📜 ⬆️ ⬇️

Rule of Three (C ++)

The rule of three (also known as the “Big Three Law” or “Big Three”) is a rule in C ++ , which states that if a class or structure defines one of the following methods, then they must explicitly define all three methods [1] :

  • Destructor
  • Copy Constructor
  • Copy Assignment Operator

These three methods are special member functions that are automatically created by the compiler if they are not explicitly declared by the programmer. If one of them has to be defined by a programmer, then this means that the version generated by the compiler does not satisfy the needs of the class in one case and probably will not satisfy in the other cases.

The amendment to this rule is that if RAII is used (from the English Resource Acquisition Is Initialization ), then the destructor used may remain undefined (sometimes referred to as the “Law of the Big Two”) [2] .

Since implicitly defined constructors and assignment operators simply copy all the data members of a class [3] , defining explicit copy constructors and assignment operators by copying is necessary in cases where the class encapsulates complex data structures or can support exclusive access to resources. And also in cases when the class contains constant data or links.

Content

Rule Five

With the release of the eleventh standard, the rule has expanded and is now called rule five. Now, when implementing a constructor, you need to implement

  • Destructor
  • Copy Constructor
  • Copy Assignment Operator
  • Motion constructor
  • Move assignment operator [4]

An example of the rule of five:

  1 #include <cstring> 
 2
 3 class RFive
 4 {
 5 private :
 6 char * cstring ;
 7
 8 public :
 9 // Constructor with initialization list and body
 10 RFive ( const char * arg )
 11 : cstring ( new char [ std :: strlen ( arg ) + 1 ])
 12 {
 13 std :: strcpy ( cstring , arg );
 14 }
 15
 16 // Destructor
 17 ~ RFive ()
 18 {
 19 delete [] cstring ;
 20 }
 21
 22 // Copy Constructor
 23 RFive ( const RFive & other )
 24 {
 25 cstring = new char [ std :: strlen ( other . Cstring ) + 1 ];
 26 std :: strcpy ( cstring , other . Cstring );
 27 }
 28
 29 // Move constructor, noexcept - for optimization when using standard containers
 30 RFive ( RFive && other ) noexcept 
 31 {
 32 cstring = other .  cstring ;
 33 other .  cstring = nullptr ;
 34 }
 35
 36 // Copy assignment statement
 37 RFive & operator = ( const RFive & other ) 
 38 {
 39 if ( this == & other )
 40 return * this ;
 41
 42 char * tmp_cstring = new char [ std :: strlen ( other . Cstring ) + 1 ];
 43 std :: strcpy ( tmp_cstring , other . Cstring );
 44 delete [] cstring ;
 45 cstring = tmp_cstring ;
 46 return * this ;
 47 }
 48
 49 // move assignment statement
 50 RFive & operator = ( RFive && other ) noexcept
 51 {
 52 if ( this == & other )
 53 return * this ;
 54
 55 delete [] cstring ;
 56 cstring = other .  cstring ;
 57 other .  cstring = nullptr ;
 58 return * this ;
 59 }
 60
 61 // You can also replace both assignment statements with the following statement.
 62 // RFive & operator = (RFive other)
 63 // {
 64 // std :: swap (cstring, other.cstring);
 65 // return * this;
 66 //}
 67 };

Copy and Share idiom

You should always avoid duplicating the same code, as when changing or correcting one section, you will have to remember to fix the rest. The idiom of copying and sharing ( English copy and swap idiom ) allows you to avoid this by re-using the copy constructor code. So for the class RFive, you will have to create a friendly swap function and implement an assignment operator by copying and moving through it. Moreover, with this implementation, there is no need for a self-assignment check.

  1 #include <cstring>   2 class RFive 3 { 4 // remaining code 5 RFive & operator = ( const RFive & other ) // Copy assignment operator 6 { 7 Rfive tmp ( other );  8 swap ( * this , tmp );  9 return * this ;  10 } 11 RFive & operator = ( RFive && other ) // move assignment operator 12 { 13 swap ( * this , other );  14 return * this ;  15 } 16 friend void swap ( RFive & l , RFive & r ) 17 { 18 using std :: swap ;  19 swap ( l . Cstring , r . Cstring );  20 } 21 // the rest of the code 22 }; 

It would also be appropriate for assignment statements to make the return value a constant reference: const RFive& operator=(const RFive& other); . The additional const will not allow us to write convoluted code, such as: (a=b=c).foo(); .

Zero

Martin Fernandez also proposed a zero rule. [5] According to this rule, it is not necessary to define any of the five functions by yourself; it is necessary to entrust their creation to the compiler (assign them the value = default; ). For owning resources, instead of simple pointers, you should use special wrapper classes, such as std::unique_ptr and std::shared_ptr . [6]

Links

  1. ↑ Stroustrup, Bjarne. The C ++ Programming Language. - 3. - Addison-Wesley, 2000. - P. 283-4. - ISBN 978-0201700732 .
  2. ↑ Karlsson, Bjorn; Wilson, Matthew. The Law of the Big Two (Unsolved) . The C ++ Source . Artima (October 1, 2004). The date of circulation is January 22, 2008. Archived on March 17, 2012.
  3. ↑ The C ++ Programming Language. - P. 271.
  4. ↑ Move Assignment Operator (Unsolved) . En.CPPReference.com . The appeal date is December 22, 2014.
  5. ↑ Rule of Zero . Flaming Dangerzone . The appeal date is July 29, 2015.
  6. ↑ Kulikov Alexander. Rule 3, 5, 0 Habrahabr (Unset.)


Source - https://ru.wikipedia.org/w/index.php?title=Pravilo_treh_ ( C%2B%2B)&oldid = 97965819


More articles:

  • Be Bop Deluxe
  • Ovchinnikova, Elena Valeryevna
  • Under the canopy of girls in bloom
  • Golenko, Konstantin Petrovich
  • Simpson-Miller, Porshiya
  • Ski Tourism in Greece
  • Lothar II (Holy Roman Emperor)
  • St. Sophia Cathedral (Tobolsk)
  • Lechin, Juan
  • Ratner, Boris Yakovlevich

All articles

Clever Geek | 2019