오늘은 C++ STL의 핵심 컨테이너인 map과 vector에 대해 깊이 파고들었다. 두 컨테이너의 시간 복잡도나 기본적인 특징은 자신 있었는데, 멤버 함수들의 미묘한 동작 차이에서 허점을 보였다. 😅 특히 map에 이미 존재하는 키를 삽입할 때의 동작과, vector의 메모리를 실제로 해제하는 방법에 대해 잘못 알고 있었다. 컨테이너를 '쓸 줄 아는 것'과 '제대로 이해하는 것'의 차이를 다시 한번 느낀 하루였다.
map::insert()와 operator[]의 삽입/수정 동작 차이 구분하기vector::clear()와 vector::shrink_to_fit()의 역할 명확히 이해하기vector 생성 및 push_back 시 size와 capacity 변화 방식 파악하기map의 삽입과 수정: insert() vs operator[]이 둘의 차이를 명확히 아는 것이 중요했다. 나는 둘 다 값을 덮어쓸 수 있다고 착각했다.
map.insert({key, value}): 새로운 Key-Value 쌍을 삽입하려고 시도한다.key가 맵에 없다면: 성공적으로 삽입된다.key가 맵에 이미 존재한다면: 삽입에 실패하고 아무것도 하지 않는다. 기존 값을 덮어쓰지 않는다! 🙅♂️map[key] = value: 특정 key에 해당하는 value에 접근한다.key가 맵에 없다면: 해당 key와 기본 생성된 value로 새 요소를 만든 후, 주어진 value를 대입한다.key가 맵에 이미 존재한다면: 기존 value를 새로운 value로 덮어쓴다.결론적으로, 값을 수정하거나 편하게 삽입하고 싶을 땐 [] 연산자를, 키의 존재 여부를 확인하며 삽입을 통제하고 싶을 땐 insert()를 쓰는 것이 맞다.
vector의 메모리 관리: clear() vs shrink_to_fit()벡터를 비운다고 해서 할당된 메모리까지 바로 사라지는 게 아니었다.
vec.clear(): 벡터 안의 모든 요소를 제거한다.size()는 0이 된다.capacity()는 변하지 않는다. 할당된 메모리는 그대로 유지된다. 이는 나중에 다시 요소를 추가할 때 또 메모리를 할당하는 비용을 줄이기 위함이다.vec.shrink_to_fit(): 사용하지 않는 여분의 메모리를 시스템에 반환해달라고 요청한다.capacity()가 현재 size()와 같아지도록 줄어든다. (컴파일러 구현에 따라 100% 보장되진 않지만 대부분 동작함)clear() 호출 후 shrink_to_fit()을 호출하면, size와 capacity 모두 0에 가깝게 만들 수 있다.map에 이미 있는 키를 insert()하면 값이 덮어써진다고 착각했다.
myMap.insert({"apple", 5}); 를 하면 기존 "apple"의 값이 5로 바뀐다.insert()는 기존 키가 있으면 실패한다. 값을 덮어쓰려면 myMap["apple"] = 5; 처럼 대괄호([]) 연산자를 사용해야 한다.vector를 비우면 메모리도 바로 해제된다고 생각했다.
myVec.clear();를 호출하면 capacity도 0이 된다.clear()는 size만 0으로 만들 뿐, capacity는 그대로 유지한다. 메모리를 실제로 해제하려면 shrink_to_fit()을 추가로 호출해야 한다.vector의 초기 capacity가 어떻게 설정되는지 헷갈렸다.
vector<int> v; 선언 후 push_back을 두 번 하면 size는 2, capacity도 2가 된다.push_back을 하면 capacity는 보통 0 -> 1 -> 2 -> 4 -> 8... 과 같이 2배씩 증가하는 전략을 사용한다. 따라서 size는 2, capacity는 2 또는 4가 될 가능성이 높다. 또한 vector<int> v(5);와 같이 생성하면 size와 capacity 모두 5로 시작한다.| 개념 | 설명 | 비고 |
|---|---|---|
map::insert() | 새 Key-Value 쌍 삽입 시도. 기존 키가 있으면 실패한다. | 반환값으로 성공 여부 확인 가능 |
map::operator[] | Key로 Value에 접근. 기존 키가 있으면 덮어쓰고, 없으면 새로 생성한다. | 가장 흔한 수정/삽입 방법 |
vector::size() | 벡터에 실제로 들어있는 요소의 개수 | push_back() 시 1 증가 |
vector::capacity() | 재할당 없이 담을 수 있는 최대 공간의 크기 | size == capacity일 때 push_back하면 증가 |
vector::clear() | 모든 요소를 제거 (size = 0). capacity는 유지된다. | 벡터를 재사용할 때 효율적 |
vector::shrink_to_fit() | capacity를 size와 같게 줄여 메모리를 해제하도록 요청한다. | 메모리를 시스템에 반환하고 싶을 때 사용 |