Effective C ++ 2e Item45

zhaozj2021-02-11  254

Miscellaneous

There are many guidelines for efficient C programming, some of which are difficult to classify. This chapter is specially arranged for these guidelines. Don't read their importance. To write efficient software, you must know what the compiler has done it behind you (give you?), How to ensure that non-local static objects have been initialized before being used, what can I get from the standard library? Where do you start to understand the design idea of ​​language underlying. The last chapter of this book, I will explain these questions and even more other questions.

Terms 45: Character C on the scenes for you, the function called

When is an empty class not empty class? ---- When the C compiler passes it. If you don't declare the following functions, your considerate compiler declare its own version. These functions are: a copy constructor, an assignment operator, a destructor, a pair of address operators. Also, if you don't declare any constructor, it will also declare a default constructor. All these functions are public. In other words, if you write this:

Class Empty {};

Word with you is the same:

Class Empty {public: EMPTY (); // Default constructor EMPTY (const EMPTY & RHS); // Copy constructor

~ Empty (); // Destructor ---- Whether // Looks out for the virtual function Empty & Operator = (const EMPTY & RHS); // Assignment operator

Empty * operator & (); // address operator const EMPTY * OPERATOR & () Const;

Now, these functions will be generated if needed, but you will easily need them. The following code will make each function generated:

Const EMPTY E1; / / Default Constructor // Destructor

EMPTY E2 (E1); // Copy constructor

E2 = E1; // Assignment operator

EMPTY * PE2 = & E2; // address operator / / (non-const)

const EMPTY * PE1 = & E1; // Address Operator // (Const)

Suppose the compiler wrote a function for you, what do these functions do? This, the default constructor and the destructor do not do anything, they just let you create and destroy the objects (for the compiler, some "behind the scenes" behavior is also placed here. Very convenient - see Terms 33 and M24.). Note that the generated destructor is generally non-virtual (see Terms 14) unless it is inherited from a base class that declares the false argument function. The default address operator is just the address of the object. These functions are actually as defined below:

Inline Empty :: Empty () {}

Inline Empty :: ~ Empty () {}

Inline Empty * Empty :: Operator & () {Return this;} inline const Empty * Empty :: Operator & () const {return this;}

As for the copy constructor and assignment operator, the official rule is that the default copy constructor (assignment operator) is a copy constructed (assignment) on the "member unit" on the class's non-static data member. That is, if m is a non-static data member of the type T in class C, and C does not declare a copy constructor (assignment operator), M will be copied by the copy constructor (assignment operator) by the type T (assignment) ) ---- If T has a copy constructor (assignment operator). If not, rules are recursively applied to M's data members until a copy constructor (assignment operator) or fixed type (for example, int, double, pointer, etc.). By default, the fixed type object copy construct (assignment) is a "bitmap" copy of the source object to the target object. For classes that are inherited from other classes, this rule applies to each layer in the hierarchy, so the user-defined constructor and assignment operator will be called in any layer being declared. .

I hope this is very clear.

But I am afraid that I haven't said clear, or give an example. Look at the definition of a NameDObject template, its instance is class that can be linked to the object:

Template class namedObject {public: namedObject (const char * name, const t & value); NamedObject (Const String & Name, Const T & Value);

...

PRIVATE: STRING NAMEVALUE; T ObjectValue;

Because the NameDObject class declares at least one constructor, the compiler will not generate a default constructor; but because there is no statement that the copy constructor and the assignment operator, the compiler will generate these functions (if needed).

Look at the call to the copy constructor:

NamedObject NO1 ("Smallest Prime Number", 2);

NamedObject NO2 (NO1); // Call the copy constructor

The copy constructor generated by the compiler must be used to initialize NO2.NAMEVALUE and NO2.ObjectValue separately with NO1.NAMEVALUE and NO1.OBJECTVALUE. NameValue type is string, string has a copy constructor (you can view String in the standard library to confirm - see Terms 49), so NO2.NAMEVALUE initializes the String copy constructor, parameter is NO1. NameValue. On the other hand, the type of NamedObject :: ObjectValue is int (because T is int), INT does not define copy constructor, so no2.objectValue is copied from NO1.ObjectValue to copy each bit (bit) ) Is initialized.

The assignment operator generated by the compiler is also working in the same way, but usually, the assignment operator generated by the compiler should work as described above, and all the code related to this must be legally and act Be reasonable. If there is an incanded in these two conditions, the compiler will refuse to generate Operator =, you will receive some diagnostic information when compiling. For example, suppose the namedObject is defined in this way, NameValue is a string reference, ObjectValue is a Const T:

Template Class NameDObject {public: // This constructor no longer has a const name parameter because NameValue // is now a non-const string reference. Char * constructor // is also invisible, because reference to point to String NamedObject (String & Name, Const T & Value);

... //, assume that there is no // declaration Operator = private: string & namevalue; // is now a reference const t ObjectValue; // is now const};

Now see what will happen below:

String newDog ("persephone"); string olddog ("satch");

NamedObject p (newDog, 2); // When I write this book, our // 爱犬 Persephone is about to pass // Her second birthday

NamedObject s (Olddog, 29); // Family dog ​​satch if it is still alive, // will be 29 years old (from my childhood)

P = s; // p The data member will happen to what?

Before assigning, p.NameValue points to a String object, and S.NameValue also points to a string, but not the same. What impact will assign P.NameValue? After assigning the value, P.NameValue should point to "String by S.NameValue", that is, the reference itself should be modified? If so, the sun comes from the west, because C has no way to let a reference point to another different object (see Terms M1). Or do the String object referred to in P.NameValue should be modified? In this case, other objects containing "pointers or references to that string or reference" will also be affected, that is, other objects that are not directly related to the direct relationship will also be affected. Is this the assignment operator generated by the compiler?

In the face of such a problem, C refuses to compile this code. If you want a class that contains a reference member, you have to define an assignment operator. For classes containing Const members (for example, ObjectValue in the class modified above), the compiler is also similar; because the modification of the Const member is illegal, the compiler will not know when implicitly generated assignment functions. How to do. Also, if the base class of the derived class declares the standard assignment operator as Private, the compiler will also refuse to generate an assignment operator for this derived class. Because the compiler is the assignment operator generated by the derived class, it should also process the base class section (see clauses 16 and M33), but if so, you have to call the base class member function that is not authorized to be accessed to the party, which is of course It is impossible. The above questions about the compiler generating function have triggered this question: What should I do if I want to use these functions? That is, if you never want to make the object to assign a value, it is interested that Operator =, what should I do? This small puzzle solution is the topic discussed in Terms 27. The mutual impact of the copy constructor generated by the pointer member and the compiler and the assignment operator is often neglected, and the discussion of this topic is discussed. Terms 11.

转载请注明原文地址:https://www.9cbs.com/read-4435.html

New Post(0)