키-값 쌍(key-value pair)을 저장하는 연관 컨테이너이다.
키는 자동으로 정렬되며, 각 키는 유일하다.
#include <iostream>
#include <string>
#include <map>
int main()
{
// --- 맵 생성 및 초기화 ---
// 기본 생성자 : 빈 맵 생성
std::map<int, int> map1;
// 균일한 초기화 : {}를 사용하여 문법을 초기화하는 방식, 초기화 리스트 맵 생성
// std::make_pair : pair 객체를 생성하는 헬퍼 함수(타입을 명시하지 않고 자동으로 타입 추론하여 pair를 생성)
// 템플릿 함수에 pair를 전달할때, 타입 추론이 필요할때 사용
// C++11 이후에는 중괄호 {} 초기화가 더 간결하고 명확하므로 권장
std::map<int, std::string> map2 = { std::make_pair(5,"감자"), std::make_pair(2,"고구마") };
std::map<int, int> map3 = { {1,2}, {10,20} };
// 복사 생성자
std::map<int, std::string> map4 = map2;
// 이동 생성자 (map4는 이제 비어있거나 유효하지 않은 상태가 될 수 있음)
std::map<int, std::string> map5 = std::move(map4);
// 반복자 범위로 맵 생성
std::map<int, std::string> map6(map2.begin(), map2.end());
// --- 맵 대입 연산 ---
std::map<int, std::string> ma = { std::make_pair(5,"감자"),std::make_pair(2,"고구마") };
std::map<int, std::string> ma2 = { std::make_pair(5,"개"),std::make_pair(12,"고양이") };
std::map<int, std::string> ma3_assign, ma4_assign, ma5_assign;
// 복사 대입 연산자
ma3_assign = ma;
// 이동 대입 연산자 (ma는 이제 비어있거나 유효하지 않은 상태가 될 수 있음)
ma4_assign = std::move(ma);
// 균일한 초기화, 초기화 리스트 대입
ma5_assign = { {1,"올이"},{122,"바둑이"} };
// --- 사용자 정의 비교 함수를 사용한 맵 생성 ---
// std::map(Compare comp): 사용자 정의 비교 함수로 맵 생성
// 람다 활용
// 문자의 길이로 정렬하는 사용자 정의 비교 함수 (긴 것부터 짧은 순으로)
// 사용자 정의 비교 함수 : 람다 함수나 함수자를 사용하여 정렬 기준을 변경 가능
// 템플릿 매개변수: 비교 함수를 사용할 때는 std::map<Key, Value, Compare> 형태로 타입을 지정해야 한다.
// decltype : 괄호 안의 타입을 자동으로 추론하기 위해 사용
auto strComp = [](const std::string& _a, const std::string& _b) { return _a.length() > _b.length(); };
std::map<std::string, int, decltype(strComp)> map7(strComp);
map7["A"] = 10;
map7["BB"] = 20;
map7["DDDGSA"] = 30;
map7["GSEEEEEE"] = 40;
std::cout << "사용자 정의 비교 함수로 맵 생성 map7" << std::endl;
for (const auto& pair : map7)
{
std::cout << "key : " << pair.first << " , value : " << pair.second << std::endl;
}
return 0;
}
#include <iostream>
#include <string>
#include <map>
int main()
{
std::map<int, std::string> ma = { std::make_pair(5,"감자"),std::make_pair(2,"고구마") };
std::map<int, std::string> ma2 = { std::make_pair(5,"개"),std::make_pair(12,"고양이") };
try
{
// at(const Key& key) : 키에 해당하는 값 반환 (범위 체크)
// 키가 존재하지 않으면 std::out_of_range 예외를 발생시킵니다.
std::string key = ma.at(100);
}
catch (std::out_of_range)
{
std::cout << "비상" << std::endl;
}
// operator[](const Key& key) : 키에 해당하는 값 반환(범위 체크 없음, 없으면 자동 생성)
// 키가 존재하지 않으면, 기본값으로 새로운 원소를 생성하고 그 참조를 반환합니다.
std::string key2 = ma2[250];
for (const auto& pair : ma2)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
return 0;
}
#include <iostream>
#include <string>
#include <map>
int main()
{
std::map<int, std::string> ma = { std::make_pair(5,"감자"),std::make_pair(2,"고구마") };
std::map<int, std::string> ma2 = { std::make_pair(50,"개"),std::make_pair(55,"고양이") };
// insert(const value_type& value)
// 삽입값 : pair
// 반환값 : pair<iterator, bool>
std::pair<std::map<int, std::string>::iterator, bool> pair = ma.insert({ 10, "고양이" });
auto pair2 = ma.insert({ 12, "독이" });
// 반환 받은 pair<iterator, bool> second에서 삽입 성공여부 확인
std::cout << pair.first->first << " , " << pair.second << std::endl;
std::cout << pair2.first->first << " , " << pair2.second << std::endl;
// insert(Iterator hint, const value_type& value)
// Iterator hint: 이 매개변수는 삽입할 위치에 대한 힌트를 제공
// std::map의 경우, 이 이터레이터는 삽입할 값보다 작거나 같은 값을 가리키는 위치여야한다
// 힌트를 제공함으로써, std::map은 이터레이터가 가리키는 위치 근처에서 요소를 삽입하려고 시도한다.
// 이는 불필요한 탐색을 줄여주고 성능을 향상시킨다.
auto it = ma.find(3);
ma.insert(it, { 3,"호랑이" });
// insert(Iterator first,Iterator last) : 범위 삽입
ma.insert(ma2.begin(), ma2.end());
// insert(std::initializer_list) : 초기화 리스트 삽입
ma.insert({25,"치킨"});
// emplace(Args&&... args) : 직접 객체 생성 (객체가 생성되는 과정에서 불필요한 복사가 없기 때문에, 삽입 성능이 향상)
ma.emplace(777,"방덕");
// emplace_hint(Iterator hint,Args&&... args)
// emplace + 힌트사용
it = ma.find(777);
ma.emplace_hint(it,776,"불덕");
std::cout << "ma" << std::endl;
for (const auto& pair : ma)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
std::cout << "ma2" << std::endl;
for (const auto& pair : ma2)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
return 0;
}
#include <iostream>
#include <string>
#include <map>
int main()
{
std::map<int, std::string> ma = { std::make_pair(5,"감자"),std::make_pair(2,"고구마") };
std::map<int, std::string> ma2 = { std::make_pair(50,"개"),std::make_pair(55,"고양이") };
std::map<int, std::string> ma3 = { std::make_pair(23,"콜라"),std::make_pair(15,"사이다") };
// erase(const Key& key) : 키로 삭제, 반환값은 삭제된 요소 개수
int count = ma.erase(5);
std::cout << "삭제된 요소 개수 : " << count << std::endl;
// erase(Iterator pos) : 반복자 위치의 요소 삭제
// erase가 반복자를 반환하는 것은 연속적인 삭제 작업, 성능 최적화, 코드의 가독성을 높이는 데 유용
auto pair = ma.erase(ma.begin());
if (pair == ma.end())
{
std::cout << "비어있습니다" << std::endl;
}
// erase(Iterator first, Iterator last) : 범위 삭제
pair = ma2.erase(ma2.begin(), ma2.end());
// clear() : 모든 요소 삭제
ma3.clear();
std::cout << "ma" << std::endl;
for (const auto& pair : ma)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
std::cout << "ma2" << std::endl;
for (const auto& pair : ma2)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
std::cout << "ma3" << std::endl;
for (const auto& pair : ma3)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
return 0;
}
#include <iostream>
#include <string>
#include <map>
int main()
{
std::map<int, std::string> ma = { std::make_pair(5,"감자"),std::make_pair(2,"고구마") };
std::map<int, std::string> ma2 = { std::make_pair(50,"개"),std::make_pair(55,"고양이") };
// find(const Key& key) : 키 검색
std::map<int, std::string>::iterator it = ma.find(1);
if (it != ma.end())
{
std::cout << it->first << " , " << it->second << std::endl;
}
else
{
std::cout << "해당하는 요소가 없습니다." << std::endl;
}
// count(const Key& key) : 키의 개수 반환
int count = ma.count(5);
std::cout << "키의 개수 : " << count << std::endl;
// lower_bound(const Key& key) : 키 이상인 첫 번째 요소
it = ma.lower_bound(2);
if (it != ma.end())
{
std::cout << it->first << " , " << it->second << std::endl;
}
// upper_bound(const Key& key) : 키 초과인 첫 번째 요소
it = ma.upper_bound(2);
if (it != ma.end())
{
std::cout << it->first << " , " << it->second << std::endl;
}
// equal_range(const Key& key) : 키와 같은 범위 반환
// 반환값 : std::pair<iterator, iterator>
//
// 첫 번째 반복자는 주어진 키와 같은 값이 처음 나타나는 위치를 가리키고
// 두 번째 반복자는 그 값이 마지막으로 나타나는 다음 위치를 가리킨다.
auto range = ma.equal_range(2);
// std::pair<std::map<int,std::string>::iterator,std::map<int,std::string>::iterator> = ma.equal_range(2);
for (auto it = range.first; it != range.second; it++)
{
std::cout << it->first << " , " << it->second << std::endl;
}
return 0;
}
#include <iostream>
#include <string>
#include <map>
int main()
{
std::map<int, std::string> ma = { std::make_pair(5,"감자"),std::make_pair(2,"고구마") };
std::map<int, std::string> ma2 = { std::make_pair(50,"개"),std::make_pair(55,"고양이") };
// size() : 맵에 저장된 요소의 개수 반환
std::cout << "ma2 size : " << ma2.size() << std::endl;
// empty() : 맵이 비어있는지 여부
std::cout << "ma empty : " << ma.empty() << std::endl;
// max_size() : 맵이 저장할 수 있는 최대 요소 개수
std::cout << "ma2 empty : " << ma2.max_size() << std::endl;
return 0;
}
#include <iostream>
#include <string>
#include <map>
int main()
{
std::map<int, std::string> ma = { std::make_pair(5,"감자"),std::make_pair(2,"고구마") };
std::map<int, std::string> ma2 = { std::make_pair(50,"개"),std::make_pair(55,"고양이") };
// begin() : 첫 번째 요소를 가리키는 반복자 반환
std::map<int, std::string>::iterator it1 = ma.begin();
// end() : 마지막 요소의 다음을 가리키는 반복자 반환
std::map<int, std::string>::iterator it2 = ma.end();
// rbegin() : 역방향 첫 번째 요소를 가리키는 반복자 반환
std::map<int, std::string>::reverse_iterator it3 = ma.rbegin();
// rend() : 역방향 마지막 요소의 다음을 가리키는 반복자 반환
std::map<int, std::string>::reverse_iterator it4 = ma.rend();
// cbegin() : 첫 번째 요소를 가리키는 const 반복자 반환
std::map<int, std::string>::const_iterator it5 = ma.cbegin();
// cend() : 마지막 요소의 다음을 가리키는 const 반복자 반환
std::map<int, std::string>::const_iterator it6 = ma.cbegin();
// crbegin() : 역방향 첫 번째 요소를 가리키는 const 반복자 반환
std::map<int, std::string>::const_reverse_iterator it7 = ma.crbegin();
// crend() : 역방향 마지막 요소의 다음을 가리키는 const 반복자 반환
std::map<int, std::string>::const_reverse_iterator it8 = ma.crend();
return 0;
}
#include <iostream>
#include <string>
#include <map>
int main()
{
std::map<int, std::string> ma = { std::make_pair(5,"감자"),std::make_pair(2,"고구마") };
std::map<int, std::string> ma2 = { std::make_pair(50,"개"),std::make_pair(55,"고양이") };
// operator== : 두 맵이 같은지 비교 (크기와 모든 요소)
// 두 맵의 크기가 같고, 모든 요소의 키와 값이 순서대로 정확히 일치해야 true를 반환합니다.
if (ma == ma2)
{
std::cout << "ma == ma2" << std::endl;
}
// operator!= : 두 맵이 다른지 비교
// 크기가 다르거나, 하나라도 다른 요소를 가지고 있으면 true를 반환합니다.
if (ma != ma2)
{
std::cout << "ma != ma2" << std::endl;
}
// operator< : 사전식 순서(lexicographical)로 작은지 비교
// 두 맵의 첫 요소부터 순서대로 비교하여, 처음으로 다른 요소가 나타나는 지점에서
// 키-값 쌍을 비교합니다. ma의 첫 키(2)가 ma2의 첫 키(50)보다 작으므로 true가 됩니다.
if (ma < ma2)
{
std::cout << "ma < ma2" << std::endl;
}
// operator> : 사전식 순서로 큰지 비교
if (ma > ma2)
{
std::cout << "ma > ma2" << std::endl;
}
// operator<= : 사전식 순서로 작거나 같은지 비교
// 작거나, 완전히 같으면 true를 반환합니다.
if (ma <= ma2)
{
std::cout << "ma <= ma2" << std::endl;
}
// operator>= : 사전식 순서로 크거나 같은지 비교
// 크거나, 완전히 같으면 true를 반환합니다.
if (ma >= ma2)
{
std::cout << "ma >= ma2" << std::endl;
}
return 0;
}
#include <iostream>
#include <string>
#include <map>
int main()
{
// 맵 초기화
std::map<int, std::string> ma = { std::make_pair(5,"감자"),std::make_pair(2,"고구마") };
std::map<int, std::string> ma2 = { std::make_pair(50,"개"),std::make_pair(55,"고양이") };
// --- 첫 번째 코드: swap ---
std::cout << "swap 전" << std::endl;
std::cout << "<< ma >>" << std::endl;
for (const auto& pair : ma)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
std::cout << "<< ma2 >>" << std::endl;
for (const auto& pair : ma2)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
// swap(std::map& other)
// 두 객체의 값을 효율적으로 교환하는 데 사용
ma.swap(ma2);
std::cout << "\nswap 후" << std::endl;
std::cout << "<< ma >>" << std::endl;
for (const auto& pair : ma)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
std::cout << "<< ma2 >>" << std::endl;
for (const auto& pair : ma2)
{
std::cout << pair.first << " , " << pair.second << std::endl;
}
std::cout << "\n----------------------------------------\n" << std::endl;
// --- 두 번째 코드: key_comp, value_comp, get_allocator ---
// key_comp() : 컨테이너의 키를 비교하는 데 사용되는 비교 함수 객체 반환
// 두 키를 비교하여 어떤 키가 더 작은지 판단
// 사용자가 정의 기준을 사용할 수 있으며, 기본적으로는 operator<를 사용
auto comp1 = ma.key_comp();
// ma의 첫 키(50)와 5를 비교합니다. 5가 50보다 작으므로 true(1)가 출력됩니다.
std::cout << "key_comp : " << comp1(ma.begin()->first, 5) << std::endl;
// value_comp() : 컨테이너의 값을 비교하는 데 사용되는 비교 함수 객체 반환
// 두 값의 크기를 비교하여 어떤 값이 더 작은지를 판단
// 키와 값이 모두 포함된 std::pair<const Key, T> 형태로 값을 비교
auto comp2 = ma2.value_comp();
for (const auto& pair : ma) // ma2는 현재 {2, "고구마"}, {5, "감자"}
{
// ma2의 각 pair와 {1, "노랑감"}을 비교합니다.
// 키 값을 기준으로 비교하므로 항상 false(0)가 출력됩니다.
std::cout << "value_comp : " << comp2(pair, { 1,"노랑감" }) << std::endl;
}
// get_allocator() : 메모리 할당자를 반환하는 함수
// 이 함수는 메모리 관리와 관련된 작업에 사용
auto alloc = ma.get_allocator();
auto p = alloc.allocate(1);
alloc.deallocate(p, 1);
return 0;
}