Effective STL Terms 39

zhaozj2021-02-11  232

Terms 39: Judgment with a pure function

I hate to do this for you, but we must start from a short vocabulary class:

A PREDICATE is returned to BOOL (or other things that can be implicitly converted to BOOL). The judgment is widely used in STL. The comparison function of standard related containers is judgments, and the determination function is often transmitted to algorithms as parameters, such as Find_IF and multiple sort algorithms. (Overview of Sort Algorithm can be found in Terms 31.) The pure function is the return value only depends on the function of the parameter. If F is a pure function, X and Y are objects, and the return value of F (X, Y) is only changed when the value of X or Y changes. In C , all data referenced by the pure function is not to be used as a parameter to be constant in the functional survival period. (Generally, such constants should be declared as const.) If a pure function reference may change in different calls, in different times, call this function to call this function to cause different results, then the pure function The definition is the opposite.

It is now clear that the judgment of the pure function is mean. Everything I have to do is that you believe that my suggestion is based. To help me do this, I hope you can forgive me for adding a burden on you to give you.

A judgment class is an imitation function class, and its Operator () function is a judgment, that is, its Operator () returns True or False. As you can expect, any STL wants a judgment, it accepts a true judgment or a judgment class object.

Just these, I promise! Now we are ready to learn why this terms provide guidance that follows the value.

Terms 38 explain that the function object is a pass value, so you should design a function object that can be copied. For judgmentary function objects, there is another reason for design when they are copied, and the behavior is good. The algorithm may be copied in the imitation function, and it is temporarily saved before use, and some algorithms achieve this freedom. An important result of this argument is that the judgment function must be a pure function.

I want to know why, let us assume that you want to violate this constraint. Consider the judgment class below the following (bad implementation). Regardless of whether the parameters are passed, it rigs only Returns True: When the third time is called. Other times it returns false.

Class Badpredicate: / / More information about this base class

Public unary_function {// Please see Terms 40

PUBLIC:

Badpredicate (): TimeScalled (0) {} // initialize Timescalled to 0

Bool Operator () (Const Widget &)

{

Return Timescalled == 3;

}

Private:

SIZE_T TIMESCALLED;

}

Suppose we use this class to remove the third Widget from a vector :

Vector vw; // Establish a vector, then

// put some widgets into

Vw.rase (transove_if (vw.begin (), // removes the third Widget;

Vw.end (), // About Erase and Remove_IF

Badpredicate ()), // See Terms 32

vw.end ());

This code looks reasonable, but for many STL implementations, it will not only remove the third element from VW, but it will also remove the sixth!

To know how this happens, you should see how remove_if is generally achieved. Remember that Remove_if is not necessarily what you want:

Template fwditerator transove_if (fwditerator begin, fwditerator end, predicate p)

{

Begin = Find_IF (Begin, End, P);

IF (begin == End) returnism;

Else {

FWDITERATOR NEXT = Begin;

Return remove_copy_if ( next, end. begin, p);

}

}

The details of this code are not important, but pay attention to the judgment P first to the FIND_IF, then pass it to the remove_copy_if. Of course, in both cases, P is a pass value - is a copy - to those algorithms. (Technically, this doesn't need to be true, but in fact, it is true. For details, please refer to Terms 38.)

Remove_if (the call to the user code to remove the third element from VW) establishes an anonymous Badpredicate object, which clears the internal Timescalled member. This object (called P in Remove_IF) is then copied to find_if, so Find_if also receives a Badpredicate object equal to 0 equal to 0. Find_if "Call" that object until it returns true, so call three times, the FIND_IF then returns to the control to remove_if. Remove_if continues to run the reclaimed radopy_copy_if, another copy of the biocar as a judgment. But P's Timescalled member is still 0! Find_if does not call P, which is called only a copy of P. As a result, the third REMOVE_COPY_IF calls its judgment, which will also return true. That's why REMOVE_IF will eventually remove two widgets from VW instead of one.

The easiest way to entertaire into the language trap is to declare your Operator () function as const in judgment classes. If you do this, your compiler will not let you change any type of data.

Class Badpredicate:

Public unary_function {

PUBLIC:

Bool Operator () (Const Widget &) Const

{

Return Timescalled == 3; // Error! In Const member functions

} // Cannot change local data

}

Because this is a straightforward method that avoids the issues we just tested, I can change the topic of this Terfeor to "make Operator () into const" in the judgment class. But that is not far enough. Even the Const member function can access Multable data members, non-Const local static objects, non-Const class static objects, namespace domains, non-Const objects, and non-Const global objects. A well-designed judgment class also guarantees that its Operator () function is independent of any kind of object. In the judgment class, the Operator () declares that CONST is necessary for the correct behavior, but not sufficient. A good operator () of course is constant, but not just this. It also has a pure function.

In front of this Terms, I highlight any STL wants to have a judgment, which will accept a true judgment or a judgment class object. It is all right in both directions. At any place where the STL can accept a judgment class object, a judgment function (possibly by the PTR_FUN change - see Terms 41) is also popular. You now understand that the Operator () function in the judgment class should be a pure function, so this restriction is also extended to the judgment function. As a judgment, this function is as bad as the object generated from the Badpredicate class: BOOL Anotherbadpredicate (Const Widget &, Const Widget &)

{

Static int TimeScalled = 0; // No! Do not! Do not! Do not! Do not! Do not! Do not!

Return Timescalled == 3; // The judgment should be a pure function,

} // Pure function is not status

No matter how you write your judgment, they should be a pure function.

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

New Post(0)