Methods and traps for deleting elements in STL sequence containers

Source: Internet
Author: User

This article from http://blog.csdn.net/canco/

3. Method for deleting elements in the list container
For list containers, since list itself has member functions of remove and remove_if, it is better to give priority to the list algorithm. For the remove function, it is relatively simple and will not be discussed. For the remove_if function, I found a major problem in vc6.0. I tried a variety of function objects, but I couldn't compile them all. By viewing the source code, I found that the remove_if () function was simplified in VC6.0 and only provided a comparison function, it can only delete elements not equal to a certain value. The source code of the remove_if () function of VC6.0 is as follows:

Typedef binder2nd <not_0000_to <_ Ty> _ Pr1;

Void remove_if (_ Pr1 _ Pr)
{
Iterator _ L = end ();
For (iterator _ F = begin (); _ F! = _ L ;)
If (_ Pr (* _ F ))
Erase (_ F ++ );
Else
++ _ F;
}

From the source code, we can see that the _ PR1 function object in remove_if is fixed as the binder2nd <not_0000_to <_ ty> format. This bug has been modified in vc7.0. The source code is as follows:

Template <class _ PR1>

Void remove_if (_ PR1 _ Pred)

{// Erase each element satisfying _ PR1

Iterator _ last = end ();
For (iterator _ first = begin (); _ first! = _ Last ;)
If (_ PRED (* _ First ))
Erase (_ first ++ );
Else
++ _ First;
}

In vc7.0, remove_if () is a member template function and can use any function object that determines the condition.

For example:

Example 8:

# Include <iostream>
# Include <string>
# Include <list>
# Include <algorithm>

Using namespace STD;
Class ctest
{
Public:
Ctest (int I): m_iprice (I ){}

Int operator = (const ctest & right) const
{
Return (m_iprice = right. m_iprice )? 1: 0;
}

Int Operator! = (Const ctest & right) const
{
Return (m_iprice! = Right. m_iprice )? 1: 0;
}

Int operator <(const ctest & right) const
{
Return (m_iprice <right. m_iprice )? 1: 0;
}

PRIVATE:

Int m_iprice;
Friend class ctestfunc;
};

Class ctestfunc
{
// Function object
Public:
Int m_value;
Ctestfunc (int I): m_value (I ){}
Bool operator () (const ctest & clfirst)
{
Return (clfirst. m_iprice = m_value )? True: false;
}
};

Void main ()
{
List <ctest> listtest;

For (INT I = 0; I <5; I ++)
{
Ctest cltest (I );
Listtest. push_back (cltest );
}

Cout <"Remove before:" <listtest. Size () <Endl;

// Delete all elements with 2

Listtest. remove_if (ctestfunc (2); // This statement cannot be compiled in vc6.0. In vc7.0

Cout <"Remove after: 2, size =" <listtest. Size () <Endl;

// Delete the elements not equal to 2. In VC6.0, The remove_if () function can only be called in this way.

ListTest. remove_if (bind2nd (not_assist_to <CTest> (), 2 ));

Cout <"remove after not equal to 2, size =" <listTest. size () <endl;

// Because the CTest class provides the = and <member functions, you can also use the remove function.

ListTest. remove (2); // delete all elements with 2

Cout <"remove after: 2, size =" <listTest. size () <endl;
}

I don't know if it is possible to break through the limitation that only function objects can be fixed as binder2nd <not_1__to <_ Ty> In VC6.0? You are welcome to give me some advice. However, using the general algorithm remove_if is only a burden of assigning values to objects several times more. If the object is not too large, the performance of the general algorithm is acceptable.

In addition, after using VC7.0, these angels feel very good, not only almost in line with Standard C ++ specifications, but also the error prompt is clearer, and the compilation speed and size of compiled files are greatly reduced, for example, if I used a large number of templates, the size of the Release executable file compiled with VC6.0 is 1.2 MB, and after being compiled with VC7.0, it is only 420 KB, I think VC7.0 has made great improvements in code optimization and template code expansion, and STL implementation, we have improved some of the previously inefficient ones, and the processing policy is basically the same as that of sgi stl.

4. Delete methods when elements in STL containers are pointers
The method for deleting elements in the container as pointers. If the element in the container is a pointer, you cannot use the method described above to delete the element by using algorithms or member functions. This will cause memory leakage, the element in the container pointing to the memory is not released. In this case, the following solutions are available:

1. Try not to use pointers as container elements.

2. if you want to reduce the burden on Object copying and assignment, and store pointers in the container, you can use the smart pointer shared_ptr In the boost library to wrap the pointer to reach the semantics referenced in the container.

3. if you do not want to use boost: shared_ptr to increase the reference count burden and think it is hard to understand the introduction of smart pointers, be careful when using pointers as elements of containers, in this case, you need to manage the memory yourself.

For example:

Example 9: Use the smart pointer shared_ptr In the boost library to wrap the pointer:

# Include <iostream>
# Include <sstream>
# Include <string>
# Include <vector>
# Include <algorithm>
# Include <list>
# Include <boost/smart_ptr.hpp> // the header file containing the smart pointer in the BOOST class library

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;
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 ){}

// Change to boost: shared_ptr <CTest> & because the element in the vector container is

// Boost: shared_ptr <CTest>

Bool operator () (const boost: shared_ptr <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 ){}

// Change to boost: shared_ptr <ctest> & because the element in the vector container is

// Boost: shared_ptr <ctest>

Bool operator () (const boost: shared_ptr <ctest> & left)
{
Return (m_iprice = (* Left). m_iprice )? True: false;
}
};

Void main ()
{
Vector <boost: shared_ptr <ctest> vecttest;
Int I;
For (I = 0; I <5; I ++)
{
Stringstream stream;
Stream <I;
String STR = stream. STR ();
Boost: shared_ptr <ctest> ptrshare (New ctest (STR, I ));
Vecttest. push_back (ptrshare );
}
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 ();
}

}

The above code will not cause memory leakage.

Example 10: manually delete the element pointer in the container:

 

# Include <iostream>
# Include <sstream>
# Include <string>
# Include <vector>
# Include <algorithm>

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;
// Declare the member function, because the vDeleteVector function needs to access the private member variable of CTest

Friend void vDeleteVector (vector <CTest *> & vectTest, const string & str );
Friend void vdeletevector (vector <ctest *> & vecttest, int iprice );
};

// Compare the values according to m_strname in the ctest class

Void vdeletevector (vector <ctest *> & vecttest, const string & Str)
{
Vector <ctest *>: iterator itvect = vecttest. Begin ();

For (; itvect! = Vecttest. End ();;)
{
If (* itvect)-> m_strname = Str)
{
// Delete the content pointed to by pointer elements in the vector container to prevent memory leakage
Delete * itVect;
ItVect = vectTest. erase (itVect );
}
Else
{
++ ItVect;
}
}
}

// Compare the values according to m_iPrice in the CTest class

Void vDeleteVector (vector <CTest *> & vectTest, int iPrice)
{
Vector <CTest *>: iterator itVect = vectTest. begin ();

For (; itVect! = VectTest. end ();)
{
If (* itVect)-> m_iPrice = iPrice)
{
// Delete the content pointed to by pointer elements in the vector container to prevent memory leakage
Delete * itVect;
ItVect = vectTest. erase (itVect );
}
Else
{
++ Itvect;
}
}
}

 
Void main ()
{
Vector <ctest *> vecttest;
Int I;

For (I = 0; I <5; I ++)
{
Stringstream stream;
Stream <I;
String STR = stream. STR ();
CTest * pclTest = new CTest (str, I );
VectTest. push_back (pclTest );
}

For (I = 0; I <vectTest. size (); I ++)
{
VectTest [I]-> vPrint ();
}

// Delete All m_strName = "5" Elements
VDeleteVector (vectTest, "3 ");
Cout <"delete 3 after:" <endl;
For (I = 0; I <vectTest. size (); I ++)
{
VectTest [I]-> vPrint ();
}

// Delete All m_iPrice = 2 Elements

VDeleteVector (vectTest, 2 );

Cout <"delete 2 after:" <endl;

For (I = 0; I <vectTest. size (); I ++)
{
VectTest [I]-> vPrint ();
}
}

Principles:

1. Use common algorithms whenever possible. I believe that STL algorithms are more efficient, elegant, and secure than their own implementations.

2. Give priority to the member functions of the container. See Item 44: Prefer member functions to algorithms with the same names in objective STL.

3. Familiarize yourself with function objects as much as possible.

4. Read the source code of STL to understand the actual work.

5. Immature optimization is the root cause of all consequences. Write code, security first.

In summary, you should be especially careful when deleting some elements in the container in STL. However, by using a common algorithm or the deletion function of the container itself, you can greatly reduce the chances of duplicate code and program errors, the code can be optimized to generate efficient code.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.