Effective STL Terms 7

zhaozj2021-02-16  82

Terms 7. When using the pointer container generated by the New, remember the DELETE pointer before the container is destroyed.

The container is considered intelligent in STL. They support forward and backward iterators; they can tell you the type of object it saved (via typef value_type); in the insertion and deletion process, they have a good memory management; they will report how many objects they have included and I can contain much objects yourself (gage through size and max_size); and, when the container is destroyed, it automatically destroyed each contained object.

With such a smart container, many programmers are no longer worried about cleaning issues. They think that the container will worry about them. In most cases, they are correct, but when the container includes the NEW production object pointer, they are not too correct. There is no doubt that when the pointer container is destroyed, it will destroy each element it is inclusive, but the "destructive function" of the pointer is just an air operation. It won't call Delete.

As a result, the following code directly leads to memory resource leaks:

Void Dosomething ()

{

Vector VWP;

For (INT i = 0; i

vwp.push_back (new widget);

... // USE VWP

} // Widgets Are Leaked Here!

When leaving VWP's scope, each element of VWP is destroyed, but this does not change the object generated by New NEW is not in the facts of DELETE. This delete action is the responsibility of the programmer, not the vector. This is actually a function, because only programmers know if the pointer needs to be deleted.

Typically, programmers want them (delete pointers). In that case (in the case), it is actually very simple.

Void Dosomething ()

{

Vector VWP;

... // AS Before

For (Vector :: item i = vwp.begin (); i! = vwp.end (), i) {

Delete * i;

}

}

This can be line, if you are not very concerned, it is just "energy". One of the questions is that the new for loop has made a lot of for_each doing things, but it is not like for_each. Another problem is that the code is not unusual security. If an exception fills in the pointer in VWP, these pointers have been thrown before. Resource leaks appear again. Fortunately, two problems can be overcome.

Modify the for_each similar code to use real for_each, you need to place the Delete action in (imitate) function objects. This is like a child game, assuming you have a child who likes to play games with STL.

Template

Struct DeleteObject: // Item 40 Describes why

Public unary_function {// this inheritance is here

Void Operator () (Const T * PTR) Const

Delete PTR;

}

}

Now you can do this:

Void Dosomething ()

{

... // AS Before

For_each (vwp.begin (), vwp.end (), deleteObject );

}

Not too lucky, it requires the object type (here: widget) that deletes DeleteObject deletion. I hate, VWP is a vector , so the deteleObject delete is of course a widget pointer! This redundancy is not just annoying because it may cause difficult BUG to appear. Imagine, for example, some people deliberately decide to inherit from String: Class Specialstring: Public String {...};

This is a dangerous product because String is the same as other standard STL containers, without the Virtual destructor. Public inheritance of an object without a false argument function is C a major misunderstanding (A Major C NO-NO) (near step details, there is a discussion in any good C book. In Effective C , it is Placed in Item 14). No matter what, some people have made this. Consider the behavior of the following code:

Void Dosomething ()

{

DEQUE DSSP;

...

For_each (DSSP.BEGIN (), DSSP.END (), // undefined behavior! deletion

DeleteObject ()); // of a deerived Object Via A Base

} // Class Pointer Where there is IS

// NO Virtual Destructor

Note that DSSP declares to save SpecialString pointers, but the author of the for_each loop tells DeleteObject, which is ready to delete the string pointer. It is easy to find what kind of error will occur. SpecialString undoubtedly a large extent as String. So someone will forget its users, they will not remember that they use specialstring instead of string.

This error can be excluded (you can also reduce the number of DELETEOBJECT users to hit the keyboard) Use the compiler to push the pivot type of the deleteObject :: Operator (). All jobs just move templates from the DeleteObject class to Operator ().

Struct deleteObject {// Templatization and Base

// Class Removed Here

Template II Templatization Added Here

Void Operator () (Const T * PTR) Const

{

Delete PTR;

}

}

The compiler knows the pointer type passed to the deleteObject :: Operator (), so it will automatically generate an instance of an Operator for the type pointer. This type of category depends on the adaptability of We abandon DELETEOBJECT. Consider how the deleteObject is designed to use, it is difficult to find a place where problems can occur.

Using this new version of DeleteObject, the SpecialString customer's code looks like this:

Void Dosomething ()

{

DEQUE DSSP;

...

For_each (DSSP.BEGIN (), DSSP.End (),

DeleteObject ()); // ah! Well-Defined Behavior!

}

Direct and type safety, just like we like.

But it is not an abnormal security. If SpecialString is produced, it has not been called for_each, an exception is thrown, and the leak will appear. This problem can be solved in many ways, but the easiest way to replace the pointer container using a smart pointer container, usually use a smart pointer to a reference count (if you are not familiar with the concept of smart pointers, you can find it in the medium-sized C reading. More Effective C , these materials are in Item 28.) STL itself does not include the intelligent pointer of the reference count, write a good - all the cases are correct - too much skill, so unless you really need this . I (Author) released a smart pointer to the number of records in More Effective C , although it is discussed by many experienced developers before release, but these years are still discussed by many experienced developers before release There is a bunch of accurate bugs found. Many of the intelligent pointers of the reference count may fail to fail. (Details Discuss in More Effective C errata)

Fortunately, hardly need to write a smart pointer, because the implementation of the confirmation is not difficult to find. There is such Share_PTR in the Boost library (Reference Terms 50). The initial example of this Terfeter can be rewritten as: Using Boost's Share_PTR.

Void Dosomething ()

{

TypedEf Boost :: Shared_ Ptr spw; // SPW = "Shared_ptr

// to widget

Vector VWP;

For (INT i = 0; i

vwp.push_back (SPW new widget); // Create a SPW from a

// widget *, the DO A

// push_back on it

... // USE VWP

} // no widgets are Leaked Here, Not

// Even if an exception is thrown

// in The Code Above

Don't be fooled by auto_ptr, don't think that the container of Auto_PTR is created, the pointer will be automatically deleted. This is terrible is the idea. It is so dangerous. I am going to use the entire provision 8. You should not use it.

It should be remember that the STL container is intelligent, but it is not enough to know if it is to delete the pointer it contains. To avoid resource leakage, the pointer should be deleted when using the pointer container. You need to use a smart pointer or manually delete each pointer before you destroy it.

Finally, a structure similar to deleteObject can easily avoid resource leakage when using the pointer container, which may make you contemplated, may create a similar deleteArray to avoid using the resource leakage when using array pointer. Of course, this is possible, but whether it is wise to another problem. Terms 13 explains why dynamic application arrays are always less than a Vector and String objects. So before you sit down and write DeleteArray, please take a look at the terms 13. If lucky, DeleteArray's era will never come.

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

New Post(0)