2009/02/18

[STL] remove algorithm 은 실제로 지우지 않는다.

vector 를 사용하다 특정 원소를 삭제하기 위해 algorithm 의 remove 를 이용하였다. vector 자체에는 remove 를 지원하지 않기 때문에... 하지만 결과는 예상을 빗나가 버렸다.

remove를 하면 원소는 사라지는 것 처럼 보이는데 vector의 크기는 그대로였다.
그래서 remove에 대한 정보를 찾아보았다.

remove 의 기능은 지정된 시작위치부터 끝위치까지 탐색하여 지워야하는 원소가 있을 경우 그 위치에 다음의 지우지 않을 원소를 덮어 써서 뒤쪽의 일부 영역을 무효화 한다.
그렇게 삭제(?)를 마치면 뒤쪽의 무효화 영역이 시작되는 iterator 를 반환한다.

실제로 지우기 위해서는 이 iterator 부터 마지막까지 erase 로 지워야한다. erase 할 경우 마지막까지 지우지 않고 iterator 만 지울 경우 다수의 원소를 삭제하고자 할 경우 정확하게 지워지지 않는다.



vector< int > vInt;
vector< int >::iterator it;

vInt.push_back( 2 );
vInt.push_back( 3 );
vInt.push_back( 4 );
vInt.push_back( 12 );
vInt.push_back( 15 );
vInt.push_back( 35 );
vInt.push_back( 2 );
vInt.push_back( 62 );
vInt.push_back( 24 );
vInt.push_back( 15 );
vInt.push_back( 91 );

TRACE0("\nsource : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

it = remove( vInt.begin(), vInt.end(), 15 );
TRACE0("\nremove 15 : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

//vInt.erase( it );
vInt.erase( it, vInt.end() );
TRACE0("\nerase : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

it = remove( vInt.begin(), vInt.end(), 2 );
TRACE0("\nremove 2 : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

//vInt.erase( it );
vInt.erase( it, vInt.end() );
TRACE0("\nerase : ");
for ( int i = 0; i < (int)vInt.size(); ++i )
TRACE1( " %d", vInt[i] );

결과
////////////////////////////////////////////////////////////////////////////////
// remove로 받은 iterator 만을 지울 경우 : vInt.erase( it )
source : 2 3 4 12 15 35 2 62 24 15 91

remove 15 : 2 3 4 12 35 2 62 24 91 15 91
// 15 삭제시 15 두 개가 삭제되고 뒤쪽의 원소들로 앞쪽으로 덮어 씌운다.
// 마지막 두 원소는 유령처럼 살아있다.
// 반환된 iterator 는 끝에서 두 번째 원소를 가리킨다.
erase : 2 3 4 12 35 2 62 24 91 91
// 반환받은 iterator 위치의 원소를 삭제할 경우 마지막에서 두 번째 원소만
// 삭제한다. 마지막 91은 여전히 살아있다.

remove 2 : 3 4 12 35 62 24 91 91 91 91
erase : 3 4 12 35 62 24 91 91 91

////////////////////////////////////////////////////////////////////////////////
// remove로 받을 iterator 에서 마지막까지 지울 경우 : vInt.erase( it, vInt.end() )
source : 2 3 4 12 15 35 2 62 24 15 91

remove 15 : 2 3 4 12 35 2 62 24 91 15 91
// 15 삭제시 15 두 개가 삭제되고 뒤쪽의 원소들로 앞쪽으로 덮어 씌운다.
// 마지막 두 원소는 유령처럼 살아있다.
// 반환된 iterator 는 끝에서 두 번째 원소를 가리킨다.
erase : 2 3 4 12 35 2 62 24 91
// 반환받은 iterator 위치부터 마지막까지 삭제할 경우 원하는 결과를 얻을 수 있다.

remove 2 : 3 4 12 35 62 24 91 24 91
erase : 3 4 12 35 62 24 91

Original Post : http://neodreamer-dev.tistory.com/255

No comments :

Post a Comment