Sign in to follow this  
Robert007

Erase elements from std::vector for socket programming

Recommended Posts

Robert007    100
Hi, Folks, There is a bug in the following loop for socket programming:
void f(std::vector<int>& socketlist) {
  std::vector::iterator itr;
  for (itr = socketlist.begin(); itr != socketlist.end(); ++itr) { // loop
     if ( 10 == *itr ) {     // simplified for some condition of the socket
         socketlist.erase( itr );
         itr--;              // bug
     }                       // the loop should continue with itr
}


Since it is used for a server program, it would be an expensive operation for working around it with a copy of socketlist. In addition, the code should work for the following cases: (1) Input vector: 10, 20, 50, 70 // remove head element 10 Output: 20, 50, 70 with itr points to 20 to loop on with the for statement (2) Input vector: 10, 20, 50, 70 // remove middle element 20 Output: 10, 50, 70 with itr points to 50 to loop on with the for statement (3) Input vector: 10, 20, 50, 70 // remove last element 70 Output: 10, 20, 50 with itr points to 50 to loop on with the for statement (4) Input vector: 10 // remove the single element 10 Output: empty vector with itr points to vec.end() to loop on with the for statement I came up with a fix that works for multiple elements cases (1), (2), (3), but not for (4), because vec::clear() invalidates all iterator (i.e., itr can not be used for looping on with the for statement). Any idea on how to do it? Thank you ! P.S. vector is the least structure for this kind of removing operation. Since it is already being used in production code, I have to stick with std::vector.
void erase(std::vector<int>& socketlist) {
   std::vector<int>::iterator itr, list_end, cur;
   for (itr = socketlist.begin(); itr != socketlist.end(); ++itr) {
         if ( 10 == *itr ) {
	    if ( socketlist.size() != 1 ) {
	       if( (itr + 1 )== socketlist.end() ) {// itr ppoints to last element
		   cur = itr -1;
	       } else {	            // other cases
		   cur = itr;
	       }			
	       list_end = std::remove(socketlist.begin(), 
                        socketlist.end(), 
                        *itr );	// now last vector item duplicated !
	       socketlist.erase(list_end, socketlist.end() );	// compact
	       itr = cur;
	    } else {            // remove a single element from the vector
	      socketlist.clear( );
	      itr = socketlist.end();			// does not work
	    }
	}			
    }		
}







Share this post


Link to post
Share on other sites
SiCrane    11839
The canonical loop for erasing from a vector while iterating over it looks like:

for (iterator itr = vec.begin(); itr != vec.end();) {
if (condition) {
itr = vec.erase(itr);
} else {
++itr;
}
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this