map과 multimap 데이터 타입이 제공하는 멤버 함수에 관해 자세히 살펴본다. 멤버 함수들이 기초적인 연산들을 제공하는 반면에, 13절과 14절에 설명하고 있는 generic 알고리듬을 사용함으로써 데이터 구조를 보다 유용하게 사용할 수 있게 된다. 

9.2.1 map의 선언과 초기화

map의 선언은 표준 라이브러리에서 자주 보아왔던 방식을 따른다. map은 템플릿 데이터 구조이며, 템플릿의 인자로 키의 타입, 키에 대응되는 값의 타입, 키를 비교하는데 사용될 비교 연산자를 지정해야 한다. 만약에 컴파일러가 디폴트 템플릿 인자(아직은 많은 회사에서 지원하지 않는 C++의 새특징)를 지원하면, 방금 언급한 템플릿 인자 중 세번째 것은 생략이 가능하고, 생략되는 경우에는 키의 타입에 정의되어 있는 less-than 연산자로 지정된다. map은 초기값없이 선언될 수 있고, 한쌍의 반복자를 사용하여 다른 컨테이너에 담긴 값들로 초기화 될 수도 있다. 후자의 경우에, 반복자는 pair 타입의 값을 가리키고 있어야 하며, 이때 첫번째 필드는 키(key)로 간주되고, 두번째 필드는 값(value)으로 간주되는 것이다. 복사 생성자를 사용하여 다른 map의 복사본을 만들어 낸다.
   // map indexed by doubles containing strings
   map<double, string, less<double> > map_one;
   // map indexed by integers, containing integers   
   map<int, int> map_two(aContainer.begin(), aContainer.end());
   // create a new map, initializing it from map two
   map<int, int> map_three(map_two);   // copy constructor
map을 다른 map에 대입할 수 있으며, swap() 연산을 사용하여 두 map간에 값을 서로 교환할 수 있다. 

9.2.2 타입 정의

map과 multimap은 많은 타입 정의들을 포함하고 있으며, 이들은 주로 선언문에서 많이 사용된다. 예를 들어, string을 정수로 매핑하는 map에 사용되는 반복자는 다음과 같이 선언된다.
    map<string, int>::iterator location;
'iterator' 뿐만 아니라, 다음과 같은 타입들이 정의되어 있다. 
 
key_type map을 인덱싱할 때 사용하는 키의 타입
value_type 맵이 담고 있는 데이터 즉 key/value pair 타입
const_iterator 자신이 가리키는 원소를 변경할 수 없는 상수 반복자
reverse_iterator 역방향으로 이동하는 역반복자
const_reverse_iterator 상수 반복자와 역 반복자의 성질을 모두 가지는 반복자
reference A reference to an underlying value.
const_reference A reference to an underlying value that will not permit the element to be modified.
size_type An unsigned integer type, used to refer to the size of containers.
key_compare A function object that can be used to compare two keys.
value_compare A function object that can be used to compare two elements.
difference_type A signed integer type, used to describe the distances between iterators.
allocator_type An allocator used by the container for all storage management.

9.2.3 삽입과 접근

insert() 연산을 사용하여 map이나 multimap에 값들을 삽입한다. 이때 인자는 반드시 키와 값의 pair이어야 한다. 이때 사용되는 pair는 map에 정의되어 있는 value_type이라는 데이터 타입을 사용하여 만든다.

   map_three.insert(map<int>::value_type(5, 7));
한쌍의 반복자를 사용하여 삽입을 수행할 수도 있는데, 다음과 같이 다른 컨테이너로부터 값을 가져올 수 있다.
   map_two.insert(map_three.begin(), map_three.end());

map(multimap은 제외)에서는 첨자 연산을 통해 값을 접근하거나 삽입할 수 있다. 단순히 키를 첨자로 사용하면 해당 값을 접근할 수 있고, 첨자 연산의 결과에 대입을 함으로써 키에 대응되는 값을 변화시킬 수 있다.

   cout << "Index value 7 is " << map_three[7] << endl;
      // now change the associated value
   map_three[7] = 5;
   cout << "Index value 7 is " << map_three[7] << endl;

9.2.4 삭제

키값을 가지고 map과 multimap으로부터 값들을 삭제할 수 있다. multimap에서는 키와 연관된 모든 원소를 삭제한다. 삭제될 원소를 반복자로 지정할 수도 있다. 예를 들면, find() 연산의 결과로 얻은 반복자를 사용할 수도 있다. 한쌍의 반복자를 사용하여 지정한 range내의 원소들을 모두 지우는 것도 가능하다.

   // erase the 4th element 4
   map_three.erase(4);
   // erase the 5th element 
   mtesttype::iterator five = map_three.find(5);
   map_three.erase(five);
   
   // erase all values between the 7th and 11th elements
   mtesttype::iterator seven = map_three.find(7);
   mtesttype::iterator eleven = map_three.find(11);
   map_three.erase(seven, eleven);
원소타입이 소멸자를 정의하고 있다면, 콜렉션으로부터 키와 값을 제거하기 전에 이 소멸자가 호출될 것이다. 

9.2.5 반복자

 No Iterator Invalidation 

begin() end() 멤버 함수는 map과 multimap의 경우 양방향 반복자를 생성한다. 이렇듯, map과 multimap에서 사용되는 반복자들은 양방향 반복자이므로 대소 비교(<, >, <=, >=)가 허용되지 않는다는 점에 유의하자(2.2절의 표를 참고). map이나 multimap에 사용되는 반복자를 참조하면 키(key)와 값(value)의 pair를 얻게 된다. 따라서, 필드명으로 first를 사용하면 키를, second를 사용하면 값(value)을 얻을 수 있다. 첫번째 필드는 상수라서 변경할 수 없지만, 두번째 필드는 주어진 키(key)와 연결된 값(value)을 변화시키는데 사용된다. 원소들은 키 필드의 순서에 따라 접근된다(?). 

rbegin() rend() 멤버 함수는 역방향으로 원소들을 생성하는 반복자들을 반환한다. 

9.2.6 검색과 카운팅

size() 멤버 함수는 컨테이너가 가지고 있는 원소의 갯수를 리턴한다. empty() 멤버 함수는 컨테이너가 비었을 때, true를 리턴하고, size()를 zero와 비교하는 것보다 대체로 빠르다. 

find() 멤버함수는 키를 인자로 취해서, 키/값 pair를 가리키는 반복자를 리턴한다. multimap의 경우에는, 가장 먼저 일치하는 값을 리턴한다. 두경우 모두, 원하는 값을 찾지 못할 때는, past-the-end 반복자를 리턴한다.

   if (map_one.find(4) != map_one.end())
      cout << "contains a 4th element" << endl;

lower_bound() 멤버 함수는 인자로 주어진 키와 일치하는 첫번째 원소를 리턴하고, upper_bound() 멤버 함수는 인자로 주어진 키와 일치하는 마지막 원소 바로 직후의 원소를 리턴한다. 마지막으로,equal_range() 함수는 lower bound와 upper bound를 담고 있는 반복자의 pair를 리턴한다. 이들 연산을 사용하는 예는 이 절의 마지막에 주어진다. 

count() 멤버 함수는 인자로 주어진 키값과 일치하는 원소의 갯수를 리턴한다. map의 경우에는 결과값이 항상 0 또는 1인 반면에, multimap의 경우에는 음수가 아닌 값이면 결과값이 될 수 있다. 단순히 콜렉션이 주어진 키로 인덱싱되는 원소를 포함하는지의 여부만을 확인하고 싶을 때는 find()의 결과값을 end-of-sequence 반복자와 비교하는 것보다는 count()를 사용하는 것이 쉬울 때가 더 많다.

   if (map_one.count(4))
      cout << "contains a 4th element" << endl;

9.2.7 원소 비교

인자가 필요없는 key_comp() value_comp() 멤버함수는 각각 key 타입 또는 value 타입의 원소를 비교할 때 사용되는 함수 객체를 반환한다. 비교할때 사용되는 값들이 콜렉션이 포함되어 있을 필요는 없으며, 이 함수들은 컨테이너에 아무런 영향을 미치지 않는다.

    if (map_two.key_comp (i, j)) // map_two.key_comp()(i, j) ?
       cout << "element i is less than j" << endl;

9.2.8 기타 map 연산

map과 multimap은 ordered 콜렉션이고, map에 대한 반복자는 pair를 반환하기 때문에, 13절과 14절에서 설명하는 함수들이 사용하기에 무의하거나 곤란한 것들이 많다. 그러나, for_each(), adjacent_find(),accumulate()들 각각은 나름대로 쓸모가 있다. 하지만, 인자로 제공되는 함수들은 키/값 pair를 인자로 취하는 것이라야 한다는 것을 반드시 기억해야 한다. 



[출처 : http://web.lge.cn:8000/system/2232]

+ Recent posts