Item 5: Understand what functions C ++ has secretly added and called for you
By Scott Meyers
Translator: fatalerror99 (itepub's nirvana)
Release: http://blog.csdn.net/fatalerror99/
When will an empty class no longer be an empty class )? The answer is when C ++ completes it. If you do not declare a copy constructor, a copy assignment operator, and a destructor ), the compiler will declare its own version for these items. In addition, if you do not declare a constructor, the compiler will declare a default constructor (default constructor) for you ). All these functions are declared as public and inline (see item 30 ). As a result, if you write
Class empty {};
In essence, it is the same as writing it like this:
Class empty {
Public:
Empty (){...}// Default constructor
Empty (const empty & RHs ){...}// Copy constructor
~ Empty (){...}// Destructor-see below
// For whether it's virtual
Empty & operator = (const empty & RHs ){...}// Copy assignment operator
};
These functions are generated only when they are needed, but they are used without doing too much. The following code will prompt every function generation:
Empty E1; // default constructor;
// Destructor
Empty E2 (E1); // copy constructor
E2 = e1; // copy assignment operator
Suppose that the compiler has written these functions for you, what do they do? Default constructor (default constructor) and destructor (destructor) mainly place "behind the scenes" Code ("behind-the-scenes" Code) to the compiler, call Constructors (constructors) and destructor (destructor) of base classes and non-static data members. Note that the generated destructor (destructor) is non-virtual (non-virtual) (see item 7) unless it is in the class (class) is inherited from a base class (base class), and the base class itself declares a virtual destructor (Virtual destructor) (in this case, the virtualness of a function (virtual) comes from base class (base class )).
For copy constructor and copy assignment operator (copy assignment operator), compiler-generated versions (the version generated by the compiler) is simply from the source object (source object) copy each non-static data member (non-static data member) to the target object ). For example, consider a namedobject template, which allows you to associate the name with the objects (object) of the T type:
Template <typename T>
Class namedobject {
Public:
Namedobject (const char * Name, const T & value );
Namedobject (const STD: string & name, const T & value );
...
PRIVATE:
STD: String namevalue;
T objectvalue;
};
Because namedobject declares a constructors, the compiler will not generate a default constructor (default constructor ). This is important. It means that if you carefully design a class (class) so that it requires constructor arguments (constructor parameter), you don't have to worry about the compiler's decision, rashly Add a Constructors (constructors) that does not require parameters ).
Namedobject neither declares copy constructor nor Copy assignment operator, so the compiler will generate these functions (if they are needed ). See, this is the usage of copy constructor (copy constructor:
Namedobject <int> No1 ("smallest prime number", 2 );
Namedobject <int> NO2 (No1 );// Callcopy Constructor
The copy constructor generated by the compiler will use no1.namevalue and no1.objectvalue to initialize no2.namevalue and no2.objectvalue respectively. The namevalue type is string, and the standard string type has a copy constructor (copy constructor). Therefore, the copy constructor (copy constructor) of string will be called using no1.namevalue as the parameter to initialize no2.namevalue. On the other hand, namedobject <int>: The objectvalue type is int (because T is int in this template instantiation (template instantiation ), int Is Built-in type (built-in type). Therefore, no2.objectvalue is initialized by copying every binary bit of no1.objectvalue.
The copy assignment operator generated by the compiler for namedobject <int> essentially performs the same action. However, generally, only when the result code is valid and there is a reasonable and understandable coincidence, compiler-generated (generated by the compiler)'s copy assignment operator (copy assignment operator) will have the behavior method I described. If either of the two tests fails, the compiler rejects generating an operator = for your class.
For example, if namedobject is defined as follows, namevalue isReferenceTo a string (to reference a string), while objectvalue isConstT:
Template <class T>
Class namedobject {
Public:
// This ctor no longer takes a const name, because namevalue
// Is now a reference-to-non-const string. the char * Constructor
// Is gone, because we must have a string to refer.
Namedobject (STD: string & name, const T & value );
... // As abve, assume no
// Operator = is declared
PRIVATE:
STD: String&Namevalue; // This is now a reference
ConstT objectvalue; // This is now const
};
Now, consider what will happen here:
STD: String newdog ("Persephone ");
STD: String olddog ("Satch ");
Namedobject <int> P (newdog, 2); // when I originally wrote this, our
// Dog Persephone was about
// Have her second birthday
Namedobject <int> S (olddog, 36); // the family dog Satch (from my
// Childhood) wocould be 36 IF SHE
// Were still alive
P = s; // What shoshould happen
// The data members in P?
Before assignment (assign value), both P. namevalue and S. namevalue lead to string objects (object), although not the same. What is the impact of assignment (Value assignment) on p. namevalue? After assignment (assign value), is the string that P. namevalue leads to? That is, the reference itself changed? If so, it violates the general rules, because C ++ does not provide a method to direct a reference to another objects (object. Another idea is P. the string objects (object) That namevalue leads is changed, which affects the string that other objects (object) -- pointers (pointer) or references (reference) continuously points, that is, what objects are not directly involved in the assignment? Is this what the compiler-generated copy assignment operator (copy assignment operator) should do?
C ++ refuses to compile the code. If you want a class (class) containing reference member to support assignment (Value assignment), you must define copy assignment operator (copy assignment operator) by yourself ). For classes (classes) containing const members (const members), the compiler will have similar behavior (like the objectvalue in the changed class (class) above ). Changing the const members (const member) is illegal, so the assignment function (Value assignment function) generated by the compiler implicitly cannot determine how to treat them. Finally, if the base classes (base class) declares the copy assignment operator (copy assignment operator) as private, the compiler rejects the derived classes (derived class) inherited from it) generate implicit copy assignment operators (implicit copy assignment operator ). After all, the copy assignment operator (copy assignment operator) generated by the compiler for the derived class also needs to process its base class parts (base class component) (see item 12), but if this is done, of course, they cannot call member functions (member functions) that derived classes (derived classes) do not have permission to call ).
Things to remember
- The compiler can implicitly generate a class default constructor (default constructor), copy constructor (copy constructor), copy assignment operator (copy assignment operator) and destructor (destructor ).