Terms 33: Beware of using similar REMOVE algorithms on a pointer
You are manageing a bunch of dynamic allocated widgets, each possibilities can be tested, you save the results pointer in a vector:
Class widget {
PUBLIC:
...
BOOL iSCERTIFIED () const; // Whether this widget is inspected
...
}
Vector
... // Dynamically allocated Widget
V.PUSH_BACK (New Widget); //'s pointer fill
When and V works for a while, you decided to remove the widget that did not pass the test because you no longer need them. Remember Terms 43 WARNING Try to call instead of explicit looping and read the terms of the explicit loop and read the relationship between REMOVE and ERAS, you will naturally think of turning to Erase-Remove usage, although this time you use remove_if:
v.rase (transove_if (v.begin (), v.end (), // delete is not tested
NOT1 (Mem_Fun (& Widget :: Iscertified)), // Widget Pointer
v.end ()); / / information about MEM_FUN
// See Terms 41
Suddenly, you started to worry about the call of Erase, because you said that the provisions of the Terms of Remember 7 About a pointer in the destruction of the container will not delete what the pointer points to the discussion. This is a reasonable concern, but here, it is too late. When calling ERASE, it is extremely possible that you have leaked resources. Worried EveryraSe, yes, but first, worry about REMOVE_IF.
We assume that before calling remove_if, V looks like this, I have pointed out the Widget that has not been tested:
After calling remove_if, typically v looks like this (containing iterators returned from Remove_iF):
If you don't understand this conversion, turn to Terms 32, because it accurately explains to call Remove - or, in this example, remove_if - what did you do.
The reason for resource leakage is now very clear. Point "Delete" pointer to Widget B and C overrides the "non-deleted" pointer behind the Vector. Nothing pointing to two widgets that have not been tested, they are not deleted, their memory and other resource are leaking.
Once remove_if and erase returns, the situation looks like this:
This is particularly obvious, and now you are also very clear why you should try to use the REMOVE and the like algorithm on the container of dynamically allocated pointers (ie REMOVE_IF and UNIQUE). In many cases, you will find the Partition algorithm (see Terms 31) is a reasonable alternative.
If you can't avoid using REMOVE on such containers, it is a way to remove the pointer before applying the ERASE-REMOVE usual method, and then sets them empty, then remove all empty pointers in the container:
Void delandNullifyUnceTified (widget * & pwidget) // If * pWidget is a
{// does not pass the test widget,
IF (! pWidget-> iScertified ()) {// Remove pointer
Delete PWIDGET; / / and set it empty
PWIDGET = 0;
}
}
FOR_EACH (v.begin (), v.end (), // Point all pointed to the Widget
DelandnullifyUncertified; / / The pointer is deleted and set to empty v.rase (transove (v.begin (), v.end (), // remove null pointer from V
Static_cast
v.end ()); // Let C can
/ / Purchatrunly launched REMOVE
// Type of the third parameter
Of course, this assumes that the vector does not contain any empty pointer you want to keep. If there is, you may have to write a loop to remove the pointer in your way. Delete elements from the container with some subtle to pay attention to where you have some submissions, you have read the terms 9 before considering that method.
If you replace the container of the pointer to the container of the smart pointer to execute the reference count, you don't exist if you delete the relevant difficulties. You can use the Erase-Remove usual method directly:
Template
Class RCSP {...}; // Smart pointer
Typedef rcsp
Vector
... // Assign Widget
v.push_back (rcspw (new widget)); // Smart pointer fills it
...
v.rase (transove_if (v.begin (), v.end (), // ERASE has not passed the test
Not1 (Mem_Fun (& Widget :: Iscertified))), // Widget's pointer
v.end ()); // No resource leak
To make these work, your intelligent pointer type must be implicitly converted to the corresponding built-in pointer type (such as widget *). That is because the container holds a smart pointer, but the member function (such as widget :: iscertified) is the internal pointer. If there is no implicit conversion, your compiler will protest.
If you happen in your program toolbox without a reference count Smart Pointer template, you should get a shared_ptr template from the Boost library. For the introduction of Boost, please see the terms 50.
No matter how you choose to process a container that processes dynamic allocation pointers, manually delete and discard the pointer before calling similar REMOVE before calling similar REMOVE, the guiding significance of this Territory is still the same: the container that is guarded in the pointer Using similar REMOVE algorithms. People who don't pay attention to this proposal can only cause resource leakage.