[effective STL] 항목 09 : 데이터를 삭제할 때에도 조심스럽게 선택

2015. 9. 7. 21:56프로그래밍/Effective STL

728x90
728x90

Erase VS Remove

연속 메모리 컨테이너(vector, deque, string)

- erase와 remove 합성문이 가장 좋은 방법이다.


양방향 반복자를 지원하는 list에도 통하지만, list는 remove를 사용하는 것이 좋다.


표준  연관 컨테이너일 때에는(set, multiset, map) remove라는 이름을 가진 어떤 것도 소용없다.

remove 알고리즘을 사용하면 컨테이너 값을 덮어써서 컨테이너를 변형시킬 수 있다.

하여간 안되고, 연관 컨테이너는 erase를 사용한다.(로그시간)

*시퀀스 컨테이너에 사용하는 remove 방법은 선형 시간.

연관 컨테이너의 erase는 상등성이 아닌 동등성에 기반하고 있다.


remove_if

조건을 이용하여 해당 요소를 삭제하고 싶을 때 사용한다.


벡터에서 삭제

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <vector>
#include <algorithm>
 
bool badValue(int x) 
    if ( x == 0)
    {
        std::cout<<"same 0"<<std::endl;
        return true;
    }
    return false
}
 
void main()
{
    std::vector<int> c;
    c.push_back(0);
    c.push_back(1);
    c.push_back(2);
    c.push_back(0);
    c.push_back(10);
 
    std::cout<<"vector size = "<<c.size()<<std::endl;
 
    c.erase(std::remove_if(c.begin(), c.end(), badValue), c.end());
 
    std::cout<<"vector size = "<<c.size()<<std::endl;
 
    for (int i : c)
    {
        std::cout<<i<<" "<<std::endl;
    }
}
cs


list 지울 때는 

c.remove_if(badValue)


연관 컨테이너일 경우

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void DoSomthing()
{
    std::map<intstd::string> c;
 
    c.insert(std::pair<intstd::string>(0"0asdf"));
    c.insert(std::pair<intstd::string>(1"1asdf"));
    c.insert(std::pair<intstd::string>(2"2asdf"));
    c.insert(std::pair<intstd::string>(3"3asdf"));
    c.insert(std::pair<intstd::string>(4"4asdf"));
        
    for (std::map<intstd::string>::iterator i = c.begin(); i != c.end(); 
        /* 반복자가 무효화 되기 때문에 직접 i++을 관리 */
        )
    {
        if (badMapValue(*i))
        {
            c.erase(i++);
            // i++을 나중에 하면 반복자 무효화로 에러
        }
        else
        {
            ++i;
        }
    }
}
cs


*기타 잡다한 로그쓰는거에 대한 이야긴데...........흠흠...


정리

컨테이너에서 특정한 값을 가진 객체를 모두 없애려면?

- vector, string, deque이면 erase-remove

- list이면 list::remove

- 표준 연관 컨테이너면? erase 멤버 함수


컨테이너에서 특정한 술어 구문을 만족하는 객체를 모두 없애려면?

- vector, string, deque이면 erase-remove_if 합성문을 사용한다.

- 컨테이너가 list이면 list::remove_if를 쓴다.

- 컨테이너가 표준 연관 컨테이너면? remove_copy_if와 swap을 쓰던가,

컨테이너 내부를 도는 루프에서 erase를 호출하면서 erase에 넘기는 반복자를 후위 증가 연산자로 증가시킨다.


루프 안에서 무엇인가를 하려면?

표준 시퀀스 컨테이너

- 컨테이너 요소를 하나씩 사용하는 루프를 작성한다.

- erase를 호출할 때마다 그 함수의 반환값으로 반복자를 업데이트하는 일을 꼭 해야한다.


표준 연관 컨테이너

- 컨테이너 요소를 하나씩 사용하는 루프를 작성한다.

- erase를 호출하면서 erase에 넘기는 반복자를 후위 증가 연산자로 증가시킨다.



728x90
반응형