Erase elements from std::vector for socket programming

Started by
2 comments, last by Zipster 13 years, 11 months ago
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
	    }
	}			
    }		
}







Advertisement
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;  }}
Thanks a lot. It works!
There is also the erase-remove idiom.

This topic is closed to new replies.

Advertisement