[effective STL] 항목 33 : remove 같은 알고리즘 사용할 때 포인터 컨테이너 주의
2016. 2. 29. 23:08ㆍ프로그래밍/Effective STL
728x90
728x90
동적으로 할당한 객체를 관리하는 컨테이너가 있을 때 주의해야 한다는 것이다.
상황(예시)
widget 객체를 동적으로 여러개 선언하고
이를 관리하는 v라는 widget 포인터 백터가 있다고 가정한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 | clss Widget { public: ... bool isCertified() const; ... }; vector<Widget* > v; ... v.push_back(new Widget); ... | cs |
widget 객체 중에 certified 되지 않은 위젯을 지우고 싶다!
1 2 | v.erase(remove_if(v.begin(), v.end(), not1(mem_fun(&Widget::isCertified))), v.end()); | cs |
not1과 mem_fun 함수들을 사용해 본 적은 없는데.. 대충 아닐때와 맴버 변수 호출 느낌인 것 같다.
32장에서 배운 것처럼 이렇게 하면 될 것 같지만 하지만 세상은 그리 쉽지 않다.
widget2와 widget3이 uncertified일때 이 위젯을 삭제하면
remove 명령을 하면 아래처럼 되는데.. 제거되는 포인터에 제거되지 않는 포인터 값을 덮어버린다.
그럼 widget2, widget3을 가리키는 포인터는 안드로메다로..... 그리고 객체는 낙동강 오리알이 된다.
이 상태로 erase를 실행하게 되면 widget2,widget3은 파워 누수가!!
그럼 삭제할 땐 어떻게 해야되나?
방법 1. uncertified 된 객체를 미리 nullptr로 만들어 루프를 돌리고 erase-remove 명령을 nullptr된 객체로 돌린다.
방법 2. 스마트 포인터를 사용한다.
방법 1
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // nullptr function void nullify_uncertified(Widget*& pWidget) { if (!pWidget->isCertified()) { delete pWidget; pWidget = nullptr; } } ... for_each (v.begin(), v.end(), nullify_uncertified); v.erase(remove(v.begin(), v.end(), static_cast<Widget*>(0)), v.end()); | cs |
nullptr로 만들어 버리는 함수를 선언한 다음 for_each로 이걸 돌린다.
그리고 erase-remove 합성문을 사용하면 됨.
방법 2
객체를 push_back 하는 곳에서 smart_ptr로 감싸는 방법이다.
1 2 3 4 5 6 7 8 9 | template <class T> class SMART { ... }; typedef SMART<Widget> SMART_WIDGET; vector<SMART_WIDGET> v; ... v.push_back(SMART_WIDGET(new Widget)); ... v.rease(remove_if(v.begin(), v.end(), not1(mem_fun(&Widget::isCertified))), v.end()); | cs |
728x90
반응형
'프로그래밍 > Effective STL' 카테고리의 다른 글
[effective STL] 항목 34 : 정렬된 범위 동작 알고리즘들 (0) | 2016.03.19 |
---|---|
[effective STL] 항목 32 : 요소 정말로 제거하기 (2) | 2016.02.28 |
[effective STL] 항목 31 : 정렬시 선택 사항들을 제대로 파악 (2) | 2016.02.27 |
[effective STL] 항목 30 : 알고리즘의 데이터 기록 범위는 충분히 크게 잡자. (0) | 2016.02.20 |
[effective STL] 항목 28 : reverse_iterator 쓸 때 base() 잘 쓰기 (0) | 2016.02.19 |
[effective STL] 항목 27 : const_iterator -> iterator는 distance와 advance를 사용하자. (2) | 2016.02.15 |
[effective STL] 항목 26 : 여러 iterator 중 쓸만한 것은 결국 iterator (2) | 2016.02.10 |