Effective C ++ 2e Item15

zhaozj2021-02-11  170

Terms 15: Let Operator = Return * this reference

C designer Bjarne Stroustrup under great effort wants to customize the user's custom type similar to the fixed type of work. That's why you can overload the operator, write type conversion functions (see Terms M5), control assignment and copy constructor, and so on. He did so much effort, then you should continue to do it.

Let us see assignment. In the case of a fixed type, the assignment operation can be chained below:

INT W, X, Y, Z;

W = x = y = z = 0;

So, you should also you can use the user-defined assignment of the type of assignment:

String w, x, y, z; // string is a type / / / / (see clause 49) by standard C library // "Custom"

W = x = y = z = "hello";

Because the binding of the assignment operator is born by the right to left, the above assignment can be resolved to:

W = (x = (y = (z = "hello")))

It is worthwhile to write it into a fully equivalent function. Unless it is a LISP programmer, the following example will be very happy because it defines a prefix operator:

W.Operator = (x.operator = (y.operator = (z.operator = ("Hello"))))))

This format is very illustrative because it emphasizes W.Operator =, X.Operator = and Y.Operator = parameters are the return value of the previous Operator = call. So the return value of Operator = must be able to be accepted as an input parameter. In a class C, the default version of the Operator = function has the following form (see Terms 45):

C & C :: Operator = (Const C &);

Under normal circumstances, it is necessary to follow the principle of = input and returning all kinds of objects, but sometimes you need to overload Operator = to allow it to accept different types of parameters. For example, the standard String type provides two different versions of assignment operators:

String & // gives a StringOperator = (Const string & rhs); // to a String

String & // Put a char * Operator = (const char * rhs); // to a string

Note that even when overloaded, the return type is also a reference to the object of the class.

One error that C programmers often makes Operator = returns Void, which seems to be unreasonable, but it hinders continuous (chain) assignment operation, so don't do this.

Another common mistake is to let Operator = return a reference object, like this:

Class widget {public: ... const widget & operator = (const widget & rhs); ...}; doing this is usually to prevent the following stupid operations in the program:

Widget W1, W2, W3;

...

(w1 = W2) = W3; // W2 assignment W1, then W3 is assigned to its result // (gives Operator = a const return value // makes this statement cannot be compiled)

This may be very stupid, but the fixed type is not stupid:

INT I1, I2, I3;

...

(i1 = i2) = I3; // legal! I2 assignment I1 // then I3 assignment I1!

This kind of practice is rarely seen, but it is ok for int, and it is also possible to me and my class. Then it should be able to you and your class. Why is it not compatible with no reason and fixed types of regular practices?

In the assignment operator defined by the default form, there are two obvious candidates: the object left on the left side of the assignment statement (the object pointing to the THIS pointer) and the object on the right side of the assignment statement (the object named in the parameter table) ). Which one is correct?

For example, a String class (assuming you want to write assignment operators in this class, see the interpretation in Terms 11) There are two possibilities:

String & string :: Operator = (const string & r Hs) {

...

Return * this; // Return to the object}

String & string :: Operator = (const string & r Hs) {

...

Return rhs; // Return to the object}

For you, this is like a half of the six one and twelve is more difficult. In fact, they have a big difference.

First, the version returned to RHS will not be compiled because RHS is a reference to const string, and Operator = to return a string reference. When you want to return a non-Const's reference and the object itself is constant, the compiler will bring you endless pain. It seems that this problem is easy to solve - only like this to re-declare operation =:

String & string :: Operator = (string & r Hs) {...}

This time, it is not possible to compile it! Let's take a look at the back part of the initial continuous assignment statement:

x = "Hello"; // and x.op = ("Hello"); the same

Because the right parameter of the assignment statement is not the correct type - it is a character array, not a string - compiler to generate a temporary String object (via the Stirng constructor - see the Terms M19) causes the function to continue running. That is, the compiler must generate a roughly like this code:

Const string Temp ("Hello"); // Generate temporary String

X = Temp; // Temporary string is passed to the Operator = The compiler generally produces such a temporary value (unless explicitly defining the required constructor - see clause 19), but pay attention to the temporary value is a const. This is important because it prevents temporary values ​​that are passed to the function. Otherwise, the programmer will be very strange to find that only the temporary value generated by the compiler can be modified and the parameters that actually pass in when the function is called. (About this is true, early version of C allows this type of temporary value to be generated, transmitted, modified, and the resultman is very strange)

Now we can know if the string's operator = declaration passes a non-Const's Stirng parameter, the application cannot be compiled: For functions that do not declare the corresponding parameters, it is illegal to pass a const object. This is a very simple rule about const.

Therefore, the conclusion is that you will not choose: When defining your assignment operator, you must return the reference to the left argument of the assignment operator, * this. If it does not do this, it will result in a continuous assignment, or if the implicit type conversion when the call is invoked, or both cases occur.

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

New Post(0)