Erase operation Problem of STL vector
One boss said csdn on the blog ("Erase operation on STL vectors", address is: http://blog.csdn.net/tingya/archive/2007/12/28/1998442.aspx) Black Strange, Holding the mentality of curiosity, I also go to gather ha lively, found a little problem, report to everyone.
The author says the following code is wrong:
vector<unsigned short> M_uintvector;
M_uintvector.push_back (10);
M_uintvector.push_back (20);
M_uintvector.push_back (30);
vector<unsigned Short>::iterator ITR;
ITR = Std::find (M_uintvector.begin (), M_uintvector.end (), 20);
M_uintvector.erase (ITR);
The author gives the "correct" code:
vector<unsigned short> M_uintvector;
M_uintvector.push_back (10);
M_uintvector.push_back (20);
M_uintvector.push_back (30);
vector<unsigned Short>::iterator ITR;
ITR = Std::find (M_uintvector.begin (), M_uintvector.end (), 20);
Delete Element
int diff = Itr-m_uintvector.begin ();
M_uintvector.erase (M_uintvector.begin () + diff);
I don't see where the "right" code is. Regardless of whether the code is correct, in terms of code, significantly increased, from the generality of the Code, iterator + diff code only applicable to random iterators, list, map, and so on non-random types of iterators can not be used. I think the first one is more beautiful and universal. As for the correctness of the code, I have tested it and worked very well.
I guess the author here should not fully describe the real work environment, there should be some restrictions are not listed, I Google a bit, found the following situation:
void Main ()
{
Vector<int> member;
Member.push_back (1);
Member.push_back (2);
Member.push_back (2);
Member.push_back (3);
Member.push_back (1);
Member.push_back (2);
Member.push_back (4);
Vector<int>::iterator ITER;
for (iter = Member.begin ();
Iter! = Member.end (); iter++)
cout<<*iter<<endl;
cout<< "Do erase--------" <<endl;
for (iter = Member.begin ();
Iter! = Member.end (); iter++)
{
if (*iter = = 2)
{
Member.erase (ITER);
}
}
for (iter = Member.begin ();
Iter! = Member.end (); iter++)
cout<<*iter<<endl;
}
At first glance, this is not the same as the first method mentioned above. There seems to be no problem. However, notice that after calling erase, go back to the for loop and continue using the iterator, and perform the + + operation.
OK, let's go over the description of the erase function:
Iterator Erase (iterator position);
Iterator Erase (iterator first, iterator last);
Now we are only concerned with side effects and return values after the function is executed. After a function call, invalidates all iterators that point to position and first. The return value is an iterator that points to the element following the last element that was deleted. So ITER in the above code is invalid after calling erase, I tested it in VS2005, and it really crashed in the operation of + +.
To solve this problem, we just discard the original iterator, use the return value, the code is as follows:
for (iter = Member.begin (); ITER! = Member.end ();)
{
if (*iter = = 2)
{
iter = Member.erase (ITER);
}
Else
{
iter++;
}
}
There are a lot of such articles on the web that are not very clear, such as "How to delete element in std::vector?" Http://www.cnblogs.com/oomusou/archive/2006/11/15/561204.html said: To delete the element in the std::vector, the formal way to use Find () Generic algorithm, if find () found, will be returned to the iterator, if not found, will be returned to Vector.end (). This is much cleaner than using a for loop.
Look at the code he gave:
Compile OK, but Run-time error!!
for (Std::vector<int>::iterator iter = Ivec.begin ();
Iter! = Ivec.end (); ++iter) {
if (*iter = = 8) {
Ivec.erase (ITER);
// }
// }
A right-to-do it.
Std::vector<int>::iterator iter = Find (Ivec.begin (), Ivec.end (), 8);
if (iter! = Ivec.end ()) {
Ivec.erase (ITER);