본문 바로가기

Today I Learned

23.02.28 - map

map

처음 선언할 때 인자로 key, value 자료형을 선언하는데 추가로 조건자를 지정할 수 있다.

map<int,int> m;
map<int,int,greater<int>> m2; //key를 내림차순으로 정렬 (기본 : 오름차순less)

map은 연관 컨테이너고 앞 뒤 구분이 없기 때문에 push_back, pop_front같은 함수는 존재하지 않고

insert를 이용해 삽입하고 erase를 이용해 삭제한다. insert하는 여러 방법들이 있다.

 

//1.pair
pair<int,int> p = {1,1};
m.insert(p);

//2.pair 임시객체
m.insert(pair<int,int>(2,2);

//3.make_pair 함수 템플릿(권장되지 않음) 
m.insert(make_pair(3,3));
//명시적으로 표현하려면 make_pair<int,int>로 표기해야함

//4.value_type (권장)
map<int,int>::value_type v(4,4);
m.insert(v);

//5.value_type 임시객체
m.insert(map<int,int>::value_type(5,5));

//6.[] 대입 연산자
map[6] = 6;

//C++11이후 등장한 추가 방식(권장)
//7.emplace
m.emplace(7,7);

//8.유니폼 초기화
m.insert({8,8});

정말 많은 방법이 있는데 주로 7번 8번을 사용하게 될 것이다. 6번 대입 연산자를 통해 원소를 추가하는 방식은 

다른 방법들과 다르게 key값이 존재하면 새로 대입하는 값으로 value를 변경한다. 다른 방법은 이미 key값이 존재하는 노드의 value를 변경시키지 않는다. 그리고 map에 데이터를 삽입할 때는 insert가 대입 연산자보다 속도가 빠르다. 그러니까 대입 연산자는 key값이 존재하는 노드의 value를 변경하고 싶을 때만 사용하자.

 

struct tagFinder
{
public:
	tagFinder(char* _pTag) : m_pTag(_pTag)
	{}

public:
	template<typename T>
	bool		operator()(T& MyPair)
	{
		if (!strcmp(MyPair.first, m_pTag))
			return true;

		return false;
	}

private:
	char*			m_pTag;
};	

....
    
map<char*, int>::iterator	iter = MyMap.find("BBB");

map<char*, int>::iterator	iter = find_if(MyMap.begin(), MyMap.end(), tagFinder("BBB"));

find함수를 이용해  key값으로 노드를 검색할 수 있다.

find_if와 조건자를 이용해 검색할 수도 있는데 여기서는 함수포인터 말고 함수객체만 사용할 수 있다.

왜냐하면 "BBB"와 같이 외부 데이터를 가지고 조건을 검사해야 하는데 함수포인터는 매개변수를 받을 수 없기 때문에 

함수객체의 매개변수로 "BBB"를 받아 생성자를 호출하고 m_pTag를 초기화 한 후 ()연산자를 오버로딩해서 m_pTag와 노드의 key값을 비교한다. 그러면 결론적으로 key가 "BBB"인 노드를 찾을 수 있다.

 

map<char*, int>::iterator	iter = MyMap.find("BBB");

그리고 맵 사용시 주의해야할 점이 있는데 string이 아니라 char*형을 key값으로 받게 되면, char*이 가리키는 문자열을 기준으로 정렬이 되는 것이 아니라 char* 포인터의 주소값을 기준으로 정렬된다. 그래서 의도한 것처럼 정렬되지는 않을 것이다. key 값이 char일 때 , char*일 때 , string일 때 정렬 기준은 다음과 같다.

 

char(wchar_t, TCHAR) 아스키 코드 기준 key값이기 때문에 알파벳 정렬됨
char*(wchar_t*, TCHAR*) 문자열의 시작 주소를 기준으로 정렬됨 (알파벳 정렬X)
string(wstring) 문자열 대소 비교 연산자가 오버로딩 되어있어 알파벳 정렬됨