STL map을 순환문 내에서 삭제시키는 것은 참 위험한 듯 하네요...
글쓴이: complexz / 작성시간: 목, 2012/06/14 - 1:34오후
vector, list등도 마찬가지지만...
map을 예로 들면
순환시키면서 특정 원소를 삭제시킬 필요가 있을 경우 그 방법이 어려울 뿐 더러
잠재적인 버그의 가능성이 높더군요.
가령...map의 경우 아래와 같이 다소 복잡한 방법으로 원소의 삭제가 가능한데요...
it = tempMap.begin(); for(;it != tempMap.end(); ){ if(조건을 만족할 경우){ tempMap.erase(it++); }else{ ++it } }
위의 코드에서 tempMap.erase(it++) 다음에 또다른 원소를 삭제할 경우
실행중 에러가 날 가능성이 많습니다.
즉, 두번째로 삭제된원소가 현재 it가 가리키는 원소의 바로 다음 원소일 경우 it++은
삭제된 원소를 가르키기 때문에 다음 순환에서 에러가 발생하는 경우죠..
삭제하는 순서를 바꾸면 되지만,
이렇게 순서를 특정하는 코드는 별로 좋지 못한거 같군요..
다른분들은 어떻게 해결을 하시는지??
Forums:
template void
template
void map_erase_if(Map& m, F pred)
{
typename Map::iterator i = m.begin();
while ((i = std::find_if(i, m.end(), pred)) != m.end())
m.erase(i++);
}
이렇게 해결합니다.
template <typename Map,
잘 이해가 가지 않습니다. 누가 설명 좀...?
잘 이해가 가지 않습니다. 누가 설명 좀...?
아주 깔끔한 generic function 이네요.
아주 깔끔한 generic function 이네요. 간단히 설명하면 다음과 같습니다
1.template 인자
Map: 임의의 (key, value) 타입을 지는 std::map
P: Predicate 비교 함수 혹은 비교 함수 객체
2. typename Map::itegator i = m.begin()
map 객체의 첫번째 원소를 가르키는 iterator(포인터라고 생각하면 됨) 획득
c++11 표준에서는 auto i = m.begin();
3. while
주어진 조건을 만족하는 (key, value) pair가 map에 존재하는 동안
4. m.erase(it++)
발견된 (key, value) pair를 삭제 후 포인터를 이동(it++)
이정도 되겠습니다.
Life rushes on, we are distracted
저는 그렇게 사용하는데요.
//
질문하신것처럼 사용합니다.
multi map 일때. 그렇게 사용하니까 에러가 없던거 같습니다.
//
그냥 map의 경우에는 이렇게 사용합니다.
//
이건.
i = m시작.
i = i 부터 m끝까지. pred를 m이 끝이 아닐때까지. 찾기.
i에 해당하는 m삭제.
왜 굳이 저렇게 하는지 모르겠습니다.
i++ 하면. 다음이 나올텐데요. i부터 m끝까지 굳이 왜 반복해서 찾아야 하나요?
----------------------------------------------------------------------------
젊음'은 모든것을 가능하게 만든다.
매일 1억명이 사용하는 프로그램을 함께 만들어보고 싶습니다.
정규 근로 시간을 지키는. 야근 없는 회사와 거래합니다.
각 분야별. 좋은 책'이나 사이트' 블로그' 링크 소개 받습니다. shintx@naver.com
아래 코드에 문제가 없습니다. map이나 set같은
아래 코드에 문제가 없습니다. map이나 set같은 associative container에서 erase를 호출하는 아주 전형적인 idiom이죠.
단지 나이들면 위의 if안의 it++, ++it를 헤깔리지 않고 코딩하는 것이 어렵다는 문제가 있을뿐입니다. 그런 면에서 map_erase_if 함수 아주 깔끔하게 잘 만든 것 같네요
Life rushes on, we are distracted
댓글 달기