This article from http://blog.csdn.net/canco/
2. Methods for deleting elements using algorithms or container member functions in STL
The preceding methods for manually writing the for loop code to delete elements in the container also have some problems. If the judgment conditions are complex and there are loop judgments, there will be exceptions in the loop, + The location of itVect should be carefully placed, and errors should be avoided. Therefore, it is not safe to manually write code to delete elements in the container. The code is repetitive and not elegant enough. There are many points to note.
In this case, you can use the remvoe () and remove_if () algorithms in STL to help. The remvoe () and remove_if () algorithms also have a problem that requires the programmer to be very careful. In general algorithms, the remove (including remove_if) function does not really delete elements from the container, but overwrites "elements to be deleted" with "undeleted elements. The returned value ForwardIterator points to the next position of the last removed element. For example, if vector {,} is executed, remove () and you want to remove all elements whose values are 3 and the result is {0, 1, 2, 4, 3 }, the returned value ForwardIterator points to the 5th elements. That is:
0 1 2 3 3 4 before removal
0 1 2 4 3 4 after Removal
Remove an element with a value of 3. The removed 3 is replaced by the last 4, and the last two elements are residual data.
Example 5:
Void main ()
{
Vector <int> vectint;
Int I;
For (I = 0; I <5; I ++)
{
Vectint. push_back (I );
If (3 = I)
{
Vectint. push_back (I );
}
}
Remove (vectint. Begin (), vectint. End (), 3 );
Cout <"after deleted, size =" <vectint. Size () <Endl;
For (I = 0; I <vectint. Size (); I ++)
{
Cout <"I =" <I <"," <vectint [I] <Endl;
}
}
The running result is:
After deleted, size = 6 // you can see from this line that the size of the removed container has not changed
I = 0, 0
I = 1, 1
I = 2, 2
I = 3, 4 // This line shows that "elements to be deleted" 3 is overwritten by "undeleted elements" 4.
I = 4, 3
I = 5, 4
Therefore, to completely delete the residual data, you should also delete it. This can be done by calling the member function erase () of the container.
Example 6:
Void main ()
{
Vector <int> vectint;
Int I;
For (I = 0; I <5; I ++)
{
VectInt. push_back (I );
If (3 = I)
{
VectInt. push_back (I );
}
}
VectInt. erase (remove (vectInt. begin (), vectInt. end (), 3), vectInt. end ());
Cout <"after deleted, size =" <vectInt. size () <endl;
For (I = 0; I <vectInt. size (); I ++)
{
Cout <"I =" <I <"," <vectInt [I] <endl;
}
}
The running result is:
After deleted, size = 4 // you can see from this line that the container size has changed after deletion.
I = 0, 0
I = 1, 1
I = 2, 2
I = 3, 4
The result shows that all elements with a value of 3 are indeed deleted.
For the vector container to store other complex objects, you can use remove_if () to add a Function Object method.
For example:
Example 7:
# Include <iostream>
# Include <sstream>
# Include <string>
# Include <vector>
# Include <algorithm>
# Include <list>
Using namespace std;
Class CTest
{
Public:
CTest (const string & str, int iPrice): m_strName (str), m_iPrice (iPrice ){}
Void vPrint ()
{
Cout <"name =" <m_strName <"price =" <m_iPrice <endl;
}
Private:
String m_strName;
Int m_iPrice;
// Because the two function objects need to access the private members of the CTest class, they are set as friends.
Friend class CStrFunc;
Friend class CIntFunc;
};
// Function object, which is compared according to string
Class CStrFunc
{
String m_str;
Public:
CStrFunc (const string & str): m_str (str ){}
Bool operator () (const CTest & left)
{
Return (m_str = left. m_strName )? True: false;
}
};
// Function object, which is compared according to int
Class CIntFunc
{
Int m_iPrice;
Public:
CIntFunc (int iPrice): m_iPrice (iPrice ){}
Bool operator () (const CTest & left)
{
Return (m_iPrice = left. m_iPrice )? True: false;
}
};
Void main ()
{
Vector <CTest> vectTest;
Int I;
For (I = 0; I <5; I ++)
{
Stringstream stream; // stream formatting character to convert int to string
Stream <I;
String str = stream. str ();
CTest clTest (str, I );
VectTest. push_back (clTest );
}
For (I = 0; I <vectTest. size (); I ++)
{
VectTest [I]. vPrint ();
}
// Delete All m_strname = "3" Elements
Vecttest. Erase (remove_if (vecttest. Begin (), vecttest. End (), cstrfunc ("3"), vecttest. End ());
Cout <"delete 3 after:" <Endl;
For (I = 0; I <vecttest. Size (); I ++)
{
Vecttest [I]. vprint ();
}
// Delete All m_iprice = 2 Elements
Vecttest. Erase (remove_if (vecttest. Begin (), vecttest. End (), cintfunc (2), vecttest. End ());
Cout <"Delete 2 after:" <Endl;
For (I = 0; I <vecttest. Size (); I ++)
{
VectTest [I]. vPrint ();
}
}
Manually compile the for loop code to delete elements in STL sequence containers. Use the common algorithm or container member function in STL to delete elements. Comparison between the two methods:
1. The code of the former is repeated.
2. The former is prone to errors and is not clear enough.
3. Efficiency:
0 1 2 3 2 5 6 7
0 1 3 2 5 6 7
0 1 3 5 6 7
Use the first method to delete all elements with a value of 2
It can be seen that every time an element is deleted, all the elements behind it move one bit forward, resulting in a large memory relocation.
0 1 2 3 2 5 6 7
0 1 3 2 5 6 6 7
0 1 3 5 6 7
Use the second method to delete all elements with a value of 2
As can be seen from the above, element 2 is overwritten by the following elements during deletion, and will not be moved to the element shift or memory relocation. The residual data will be left to the end of all deletions, and will not cause a large memory relocation, therefore, the latter method is much more efficient than the former method.