map
-> map의 원소는 key와 value를 한 쌍으로 가진다.
-> 각 원소들은 삽입 시에 key값에 따라 자동 정렬이 발생한다.(순회 가능)
-> 노드 기반 컨테이너들 중 유일하게 key값을 통한 임의 접근이 가능하다.
-> 리소스 탐색용으로 많이 사용된다.
-> 단, 중복된 key값은 허용하지 않는다.
map
->map은 key와 value를 한 쌍으로 가진 컨테이너이다.
-> key로 사용할 자료형과 value로 사용할 자료형을 <>안에 명시해주면 된다.
-> 명시한 순서대로 key와 value의 타입이 결정된다.
map<int, int> Mymap;
map의 원소 삽입
map은 원소 삽입 시 key 값에 따라 자동 정렬이 발생한다.
-> 자동 정렬이 발생하기 때문에 앞, 뒤 원소 삽입의 의미가 없으므로 push 함수를 지원하지 않는다.
map의 원소
pair 객체(구조체)
map은 원소로 객체를 가진다.
pair<int, int> Mypair(1, 100);
구조체이기 때문에 읽기/쓰기가 가능하다.
Mypair.first = 10;
Mypair.second = 100;
(key) (value)
cout << Mypair.first << ", " << Mypair.second << endl;
map의 원소 삽입 방법
#1. pair 객체
pair<int, int> Mypair<1, 100>;
Mymap,insert(Mypair);
auto iter = Mymap.begin();
for(; iter != Mymap.end(); ++iter)
{
iter->second += 10;
cout << iter->first << ", " << iter->second << endl;
}
pair<int, int>(1, 100);
Mymap.insert(pair<int, int>(1, 100));
Mymap.insert(pair<int, int>(2, 200));
Mymap.insert(pair<int, int>(3, 300));
map의 key값(iter->first)은 상수이기때문에 대입이 불가능하다.
#2. make_pair()
인자로 2가지 정볼르 받아 첫 번째 인자는 key값으로, 두 번째 인자는 value값으로 만든 pair를 반환한다.
Mymap.insert(make_pair(1, 100));
Mymap.insert(make_pair(2, 200));
Mymap.insert(make_pair(3, 300));
#3. value_type
map 컨테이너 내부에 구현된 pair객체라고 생각하면 된다.
map<int, int>::value_type MyValuetype(1, 100);
cout << MyValuetype.first << ", " << MyValuetype.second << endl;
MyValuetype.first = 10; // 불가능
MyValuetype.second = 1000;
Mymap.insert(MyValuetype);
Mymap.insert(map<int, int>::value_type(2, 200));
Mymap.insert(map<int, int>::value_type(3, 300));
value_type의 key값(first) 또한 상수이기때문에 대입이 불가능하다.
#4. index 방식
-> []를 사용한다.
Mymap[1] = 100;
Mymap[2] = 200;
for(auto pair : Mymap)
{
cout << pair.first << ", " << pair, second << endl;
}
insert 와 []의 차이점
-> insert : 중복된 key값이 있을 경우 무시한다.
-> [] : 중복된 key값이 있을 경우 value를 수정한다.
map은 중복되는 key값을 허용하지 않기 때문에 []을 통한 삽입은 자주 사용하지 않는다.
#5. emplace()
모든 컨테이너의 삽입 용어를 획일화 하기 위해 추가되었다.
vector : emplace_back()
list : emplace_back() / emplace_front()
map : emplace()
Mymap.emplace(1, 100);
Mymap.emplace(2, 200);
Mymap.emplace(3, 300);
단, key의 타입이 다를 경우 오류가 발생한다.
#6. 유니폼 초기화
-> {}를 사용한다.
Mymap.insert({1, 100});
-> 초기화가 필요한 것들에 대해서 모든 초기화가 가능하다.
-> 가독성이 떨어진다는 단점이 있다.
map의 삽입 정리
map<int, int> Mymap;
// index 방식
Mymap[0] = 0;
// pair 객체
Mymap.insert(pair<int, int>(1, 100));
// 첫 번째 인자는 key값으로, 두 번째 인자는 value값으로 만든 pair를 반환
Mymap.insert(make_pair(2, 200));
// map 컨테이너 내부에 구현된 pair 객체
Mymap.insert(map<int, int>::value_type(3, 300));
// 획일화된 삽입 용어(C++11 문법)
Mymap.emplace(4, 400);
// 유니폼 초기화(C++11 문법)
Mymap.insert({ 5, 500 });
}
map의 반복자
map<int, int> Mymap;
map<int, int>::iterator iter = Mymap.begin();
++iter;
++iter;
cout << iter->first << ", " << iter->second << endl;
map은 노드기반 컨테이너이기 때문에 양방향접근 반복자를 사용한다.
map의 중간 삽입
Mymap.insert(pair<int, int>(1, 100));
Mymap.insert(make_pair(2, 200));
Mymap.insert(map<int, int>::value_type(3, 300));
Mymap.emplace(4, 400);
Mymap.insert({ 5, 500 });
map<int, int>::iterator iter = Mymap.begin();
++iter;
++iter;
Mymap.insert(iter, {10, 1000});
for(auto pair : Mymap)
cout << pair.first << ", " << pair.second << endl;
여기서 우리가 원하는 값은 1, 2, 10, 3, 4, 5 이다.
하지만 map은 key값에 따라 자동 정렬이 발생한다.
그렇기 때문에 결과는 1, 2, 3, 4, 5, 10이 나오게 된다.
-> 중간 삽입의 의미가 없게된다.
map의 중간 삭제
Mymap.insert(pair<int, int>(1, 100));
Mymap.insert(make_pair(2, 200));
Mymap.insert(map<int, int>::value_type(3, 300));
Mymap.emplace(4, 400);
Mymap.insert({ 5, 500 });
map<int, int>::iterator iter = Mymap.begin();
map<int, int>::iterator iter_end = Mymap.end();
++iter;
++iter;
Mymap.erase(iter);
iter = Mymap.begin();
for(; iter != iter_end; ++iter)
{
cout << iter->first << ", " << iter->second << endl;
}
map의 중간 삭제는 자동 정렬 발생과는 상관이 없으므로
정상적으로 원하는 값이 나오게 된다.(다른 컨테이너 방식과 같음)
map의 탐색_find()
cout << Mymap[10] << endl;
탐색을 하기 위해 []를 사용할 경우 key값이 있으면 value를 반환한다.
하지만, key값이 없을 경우 원소를 삽입하게된다.
-> 새로운 원소를 삽입 후에 그 원소에 있는 value 값을 반환
find()의 사용 방법은 다음과 같다.
map<int, int> Mymap;
Mymap.insert(pair<int, int>(1, 100));
Mymap.insert(make_pair(2, 200));
Mymap.insert(map<int, int>::value_type(3, 300));
Mymap.emplace(4, 400);
Mymap.insert({ 5, 500 });
auto iter = Mymap.find(4);
if(iter != Mymap.end())
{
cout << iter->first << ", " << iter->second << endl;
}
find 함수의 문제점
-> find함수는 단순 비교이다.
map<const char*, int> Mymap;
Mymap.emplace("AAA", 10);
Mymap.emplace("BBB", 20);
Mymap.emplace("CCC", 30);
auto iter = Mymap.find("BBB");
char szBuff[16] = "AAA";
auto iter = Mymap.find(szBuff);
if(iter != Mymap.end())
{
cout << iter->first << ", " << iter->second << endl;
}
else
{
cout << "탐색 불가" << endl;
}
-> key값으로 저장하는 것은 문자열, Data영역의 주소이다.
-> 탐색하고자 하는 szBuff는 지역 변수 stack영역에 할당이 되므로 탐색 불가가 출력이 된다.
-> 즉, 문자열을 비교하는 것이 아니라 단순 주소를 비교하고 있는 것이다.
map 컨테이너의 key값이 포인터일 경우 탐색 방법
-> 알고리즘 함수의 find_if를 사용한다.
-> find_if는 단항 조건자여야 한다.
-> 즉, 함수 객체를 통해서 탐색을 하면 된다.
class CStringCmp
{
public:
CStringCmp(const char* _pString) : m_pString(_pString) {}
public:
template <typename T>
bool operator()(T& _dst)
{
return !strcmp(m_pString, _Dst.first);
}
private:
const char* m_pString;
};
void main()
{
map<const char*, int> Mymap;
Mymap.emplace("AAA", 10);
Mymap.emplace("BBB", 20);
Mymap.emplace("CCC", 30);
char szBuff[16] = "AAA";
auto iter = find_if(Mymap.begin(), Mymap.end(), CStringCmp(szBuff));
if (iter != Mymap.end())
{
cout << iter->first << ", " << iter->second << endl;
}
else
{
cout << "탐색 불가" << endl;
}
}
'Programming > STL' 카테고리의 다른 글
C++(STL Container) 반복자(iterator) (0) | 2020.09.28 |
---|---|
C++(STL Container) vector (0) | 2020.09.27 |
C++(STL Container) list (0) | 2020.09.27 |
C++ STL이란? (0) | 2020.09.27 |
STL map / unordered_map 과 map이 사용하는 자료구조 (0) | 2020.05.07 |