2026. 3. 10. 23:22ㆍTIL
C++ STL이란?
STL(Standard Template Library)은 C++ 표준 라이브러리의 일부로, 컨테이너, 알고리즘, 반복자 등의 템플릿 기반 구성 요소를 포함한다.
STL을 잘 활용하면 다양한 자료구도와 알고리즘을 직접 구현하지 않고도 사용할 수 있다.
컨테이너
컨테이너는 데이터를 저장하고 관리하기 위한 자료구조를 의미한다. 컨테이너는 배열처럼 데이터를 담는 역할을 하지만, 데이터의 저장 방식과 제공하는 기능에 따라 여러 종류로 나뉜다.
컨테이너의 특징
- 템플릿 기반 자료구조
- STL컨테이너는 대부분 템플릿으로 구현되어 있다.
- 따라서 하나의 컨테이너로 정수, 실수, 문자열 등 다양한 타입의 데이터를 저장할 수 있다.
- 자동 메모리 관리
- 컨테이너는 내부적으로 메모리를 자동 관리한다.
- 개발자는 데이터 관리 로직에 집중할 수 있다.
- 반복자(Iterator) 제공

컨테이너의 구조는 다음과 같다.
컨테이너는 데이터를 저장하는 공간이고, 반복자는 데이터에 접근하기 위한 도구이다.
이 컨테이너를 사용하는 이유는 다음과 같은 장점 때문이다.
- 다양한 자료구조를 쉽게 사용할 수 있다.
- 메모리 관리가 자동으로 이루어진다.
- 반복자를 통해 데이터 접근 방식이 통일된다.
- 코드의 안정성과 생산성이 높아진다.
다음은 컨테이너 중에서 벡터와 맵을 알아보려고 한다.
벡터
벡터(vector)는 C++ STL에서 제공하는 대표적인 순차 컨테이너이다.
배열과 매우 비슷한 구조를 가지고 있지만, 크기가 자동으로 조절된다는 점에서 일반 배열과 차이가 있다.
일반 배열은 처음 선언할 때 크기를 정하면 이후에 변경하기 어렵지만, 벡터는 원소가 추가되거나 삭제되면 내부적으로 메모리를 재할당하면서 크기를 자동으로 관리한다.
벡터의 특징
- 템플릿 기반 컨테이너
- 벡터는 템플릿 클래스로 구현되어 있기 때문에 특정 타입에 제한되지 않는다. 다양한 타입의 데이터를 하나의 컨테이너 구조로 저장할 수 있다.
//예시
vector<int> numbers;
vector<double> values;
vector<string> words;
- 크기가 자동으로 조절되는 동적 배열
- 벡터는 내부적으로 동적 배열구조로 동작한다.
- 임의 접근이 가능
- 벡터는 배열과 마찬가지로 인덱스를 이용해 특정 위치의 데이터에 바로 접근할 수 있다.
- 끝에서 삽입 / 삭제가 효율적
- 벡터는 맨 뒤에서 원소를 추가하거나 삭제하는 작업이 효율적이다.
- 중간 위치에서 삽입이나 삭제가 발생하면 뒤에 있는 원소들을 이동해야 한다.
벡터의 선언
벡터는 다양한 방법으로 선언할 수 있다.
기본선언
vector<int> vec;
빈 벡터가 생성되며 초기 크기는 0이다.
특정 크기와 초기값으로 선언
vector<int> vec(5, 10);
크기는 5에 모든 값을 10으로 채운
[10, 10, 10, 10, 10] 의 벡터가 생성된다.
초기화 리스트 사용
vector<int> vec = {1,2,3,4,5};
{} 중괄호를 이용해서 직접 초기 데이터를 넣을 수 있다.
벡터 복사
vector<int> vec1 = {1,2,3,4,5};
vector<int> vec2(vec1);
기존 벡터의 복사본을 만들 때 사용된다. 메모리 값은 서로 독립되어 있다.
2차원 벡터
vector<vector<int>> vec2D(3, vector<int>(4,7));
7 7 7 7
7 7 7 7
7 7 7 7
이렇게 행이 3, 열이 4, 모든 값을 7로 채운 2차원 벡터를 선언할 수 있다.
push_back()
vec.push_back(10);
vec.push_back(20);
vec.push_back(30);
이런식으로 벡터의 맨 뒤에 원소를 추가할 수 있다.
[ ]
↓
[10]
↓
[10 20]
↓
[10 20 30]
pop_back()
[10 20 30]
↓
pop_back()
↓
[10 20]
벡터의 맨 마지막 원소를 제거한다.
size()
현재 벡터에 저장된 원소 개수를 반환한다.
vec.size()
[10 20 30]
size = 3
erase()
특정 위치의 원소를 삭제할 때 사용한다.
vec.erase(vec.begin() + 1);
---------------
[10 20 30 40 50]
20 삭제
[10 30 40 50]
또는 범위를 삭제할 수도 있다.
vec.erase(vec.begin()+1 , vec.begin()+3)
--------------
[10 20 30 40 50]
↓
[10 50]
하지만 벡터의 특성상 맨 뒤에서 삭제/삽입이 효율적이다. erase는 중간 데이터를 이동하는 데에 비용이 큰 연산이다.
벡터 사용의 장점
- 배열처럼 빠른 인덱스 접근 가능
- 크기가 자동으로 확장되는 동적 배열
- 메모리를 자동으로 관리
- STL과 함께 편리하게 데이터 처리 가능
맵 (Map)
맵은 키(key)와 값(value)을 한 쌍으로 저장하는 STL 컨테이너이다.
배열이 인덱스를 이용해 데이터를 찾는 구조라면, 맵은 특정 키를 이용해 원하는 값을 빠르게 찾을 수 있는 자료구조이다.
예를 들면 전화번호부처럼 생각해볼 수 있다.
이름(Key) 전화번호(Value)
Alice → 010-1234-1111
Bob → 010-2222-3333
Charlie → 010-4444-5555
이런식으로 키를 이용해 값을 찾는 구조가 바로 맵이다.
특징
- 데이터는 항상 Key - value 쌍(pair)으로 저장된다.
- Key를 기준으로 자동으로 정렬된다.
20 → Banana
5 → Apple
15 → Cherry
10 → Grapes
↓↓↓↓↓
5 → Apple
10 → Grapes
15 → Cherry
20 → Banana
따라서 사용자가 정렬을 할 필요가 없다.
- 같은 키는 하나만 존재할 수 있다. 중복된 키를 허용하지 않는다.
map<int,string>
1 → Apple
1 → Banana (불가능)
같은 키를 넣으면 기존 값이 덮어쓰여지거나 삽입이 실패한다.
맵의 선언
맵 선언의 형식은 다음과 같다.
map<KeyType , ValueType>
예시
map<int, string>
map<string, int>
map<string, string>
이렇게 Key 타입과 Value 타입 두 가지를 지정해야 한다.
맵의 주요 동작
insert()
맵에 새로운 Key - Value 데이터를 추가하는 함수이다.
myMap.insert(make_pair(1, "Apple"));
make_pair를 이용해서 pair 객체를 생성한 후 추가할 수 있다.
myMap.insert({4, "Dog"});
{} 중괄호를 사용해서 추가할 수 있다.
myMap[7] = "Giraffe";
myMap[8] = "Horse";
myMap[9] = "Iguana";
[]대괄호를 사용해서 추가하는 방식으로 가장 많이 사용되는 방식이다.
find()
맵에서 특정 Key가 존재하는지 찾는 함수이다.
auto it = myMap.find(key);
동작 방식
Key 존재 → 해당 위치 iterator 반환
Key 없음 → map.end() 반환
size()
맵에 저장된 Key-Value 쌍의 개수를 반환한다.
map<int, string> myMap;
myMap[1] = "Apple";
myMap[2] = "Banana";
myMap[3] = "Cherry";
cout << "Map size: " << myMap.size() << endl;
출력값 : 3
erase()
특정 Key를 가진 데이터를 삭제한다.
myMap.erase(2);
삭제 전
1 → Apple
2 → Banana
3 → Cherry
삭제 후
1 → Apple
3 → Cherry
존재하지 않는 키 삭제
myMap.erase(40)
결과
Key 40 not found. No deletion performed.
존재하지 않는 키는 삭제되지 않는다.
clear()
맵의 모든 데이터를 삭제한다.
핵심 정리
- Key와 Value가 쌍(pair)형태로 저장된다.
- key 기준으로 자동 정렬된다.
- 같은 Key는 중복될 수 없다.
- Key를 이용해 데이터를 빠르게 검색할 수 있다.
- 삽입 / 삭제 / 탐색을 위한 다양한 변수( insert, find, erase, clear ) 를 제공한다.
알고리즘 (Algorithm)
STL에서는 다양한 범용 알고리즘을 제공한다.
이 알고리즘들은 특정 컨테이너에 종속되지 않고 배열, vertor, string 등 여러 컨테이너에서 동일한 방식으로 사용할 수 있다.
예를 들어 데이터를 정렬하는 기능, 특정 값을 찾는 기능 등 같은 것들을 직접 구현하지 않고 STL 함수로 바로 사용할 수 있다.
sort
sort는 컨테이너 내부 데이터를 정렬하는 함수이다.
기본 타입(int, double 등)은 기본적으로 오름차순 정렬이다.
사용자가 직접 정렬 기준을 정의할 수도 있다.
기본 정렬
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int arr[] = {5, 2, 9, 1, 5, 6};
int size = sizeof(arr) / sizeof(arr[0]);
sort(arr, arr + size);
}
여기서 sort(arr, arr + size);에서
arr < 시작위치
arr + size < 끝 위치
이다. 이는 정렬할 범위를 지정하는 것이다.
내림차순
큰 숫자가 앞에 오도록 함수를 만들면 된다.
bool compare(int a, int b)
{
return a > b;
}
sort(arr, arr + size, compare);
이런식으로
sort(시작, 끝, 정렬함수)를 사용해서 정렬할 수 있다.
vector 정렬
vector도 동일한 방식으로 정렬할 수 있다.
vector<int> vec = {5,2,9,1,5,6};
sort(vec.begin(), vec.end());
// vec.begin() < 시작
// vec.end() < 끝
내림차순도 위와 마찬가지로 함수를 지정해서
sort(vec.begin(), vec.end(), compare);
로 선언하면 내림차순 지정이 가능하다.
Class 객체 정렬
class Person
{
string name;
int age;
};
클래스가 이렇게 지정되어 있고,
정렬 기준을
1. 나이 오름차순
2. 나이가 같으면 이름 오름차순
이렇게 지정해보려고 한다.
bool compareByAgeAndName(const Person& a, const Person& b)
{
if(a.getAge() == b.getAge())
return a.getName() < b.getName();
return a.getAge() < b.getAge();
}
함수를 선언하고,
vector<Person> people = {
Person("Alice", 30),
Person("Bob", 25),
Person("Charlie", 35),
Person("Alice", 25)
};
sort(people.begin(), people.end(), compareByAgeAndName);
클래스를 인스턴스화한 후 정렬 함수를 사용하면 정상적으로
Alice (25)
Bob (25)
Alice (30)
Charlie (35)
정렬된 모습을 확인할 수 있었다.
find
find는 컨테이너 내부에서 특정 값을 찾는 알고리즘 함수이다.
find(시작, 끝, 찾을값)
사용 형식은 다음과 같다.
벡터에서 값 찾기
auto it = find(vec.begin(), vec.end(), 30);
아까와 같이 auto it로 반복자를 이용해서 30을 찾아보려고 한다.
10 20 30 40 50에서 저 코드를 실행시키면
위치 : 2 가 출력된다.
배열에서 값 찾기
auto it = find(arr, arr + size, 4);
arr + size에서 size는
arr / arr[0]으로 구한 배열의 크기이다.
arr + size를 해주는 이유는 이 find에서 찾는 끝 부분은 포함이 되지 않아 끝 부분의 전까지 순환한다.
그래서 vec.end() 또한 벡터의 마지막값보다 하나 더 뒤의 위치를 가리킨다.
숫자 배열이 1 2 3 4 5 라고 하면
위 코드의 실행 값은
위치 : 3
으로 인덱스3이 출력될 것이다.
문자열에서 문자 찾기
string str = "hello world";
auto it = find(str.begin(), str.end(), 'o');
다음과 같은 문자열에서도 find를 이용해서 찾을 수 있다.
위 코드의 실행 결과로는
o의 위치가 인덱스4이므로
위치 : 4
가 출력될 것이다.
문자열의 찾기에서는 가장 앞에 있는 글씨만 찾는다.
find 동작 방식
- find(first, last, value) 형식으로 사용한다.
- 찾으면 해당 위치의 반복자(iterator)를 반환한다.
- 찾지 못하면 last iterator를 반환한다.
- if ( it != end() ) 조건을 이용해서 찾았는지 확인할 수 있다.
알고리즘 핵심 정리
- STL은 컨테이너와 독립적으로 동작하는 알고리즘을 제공한다.
- 대표적인 알고리즘
- sort() : 데이터 정렬
- find() : 특정 값 탐색
- iterator(반복자)를 이용해 다양한 컨테이너에서 동일한 방식으로 사용할 수 있다.
- 사용자 정의 함수를 이용해 정렬 기준을 직접 설정할 수 있다.
반복자 ( Iterator )
컨테이너(Vercor, map 등)와 알고리즘(sort, find 등)을 살펴보았는데, 이 두 가지가 함께 동작할 수 있는 이유는 바로 반복자(Iterator) 때문이다.
반복자는 컨테이너 내부 원소를 가리키는 객체로, 컨테이너의 내부 구조를 몰라도 일관된 방식으로 데이터에 접근할 수 있도록 해준다.
즉, 반복자는 컨테이너와 알고리즘 사이를 연결해주는 역할을 한다.
컨테이너 ←→ 반복자 ←→ 알고리즘
vector iterator sort
map find
list
반복자의 개념
반복자는 컨테이너 안의 데이터를 가리키는 포인터와 비슷한 개념이다.
vector<int>
[10] [20] [30] [40]
↑
iterator
벡터가 다음과 같다면 반복자는 현재 위치의 데이터를 가리킨다.
따라서
*it → 현재 값 접근
++it → 다음 요소 이동
이렇게 연산이 가능하다.
순방향 반복자
순방향 반복자(forward iterator)는 컨테이너의 첫 번재 원소부터 마지막 원소가지 순차적으로 이동하는 반복자이다.
반복자를 사용할 때 가장 기본이 되는 함수는 다음 두 가지이다.
begin() → 첫 번째 원소를 가리킴
end() → 마지막 원소 다음 위치
아까 find에서 설명했듯 end()는 마지막 원소의 다음 위치이다.
vector
[1] [2] [3] [4] [5]
↑ ↑
begin() end()
그렇기 때문에 반복문을 다음과 같이 만들 수 있다.
for(iterator = begin(); iterator != end(); ++iterator)
1부터 10까지 반복한다고 했을 때, 10은 아직 end()에 도달하지 못했으므로 10까지는 순환 후 반복문이 종료된다.
맵에서 순방향 반복자
맵에서는 반복자가 Key - Value 쌍을 가리킨다.
for(auto it = scores.begin(); it != scores.end(); ++it)
{
cout << it->first;
cout << it->second;
}
여기서
it -> first 는 Key
it -> second 는 Value이다.
find와 반복자
auto it = find(words.begin(), words.end(), target);
target에 설정된 단어를 찾는다.
it != end()는 찾았을 경우,
it == end()는 찾지 못 했을 경우에 it에 반환된다.
역방향 반복자
역방향 반복자(reverse iterator)는 컨테이너의 마지막 원소부터 첫 번째 원소까지 거꾸로 순회하는 반복자이다.
사용되는 함수로는
순방향 반복자의 앞에 " r "을 붙여 사용한다.
rbegin() → 마지막 원소
rend() → 첫 원소 이전 위치
find나 sort 등에
sort(rbegin(), rend());
를 하면 역방향으로 정렬된다.
벡터 역방향 반복자
vector<int> numbers = {10,15,20,25,30};
for(auto it = numbers.rbegin(); it != numbers.rend(); ++it)
{
if(*it % 2 == 0)
cout << *it;
}
이렇게 사용하면
30 25 20 15 10 순서대로 순환하게 되고,
출력은
30 20 10 이 출력된다.
맵 역방향 반복자, 역방향 find
전부 begin(), end()를 -> rbegin(), rend()를 이용해서 사용하면 역방향으로 참조한다.
핵심 정리
- 반복자는 컨테이너 내부 데이터를 가리키는 객체이다.
- 알고리즘은 반복자를 이용해 컨테이너와 독립적으로 동작한다.
- begin() : 첫번째 원소
- end() : 마지막 원소 다음 위치
- rbegin() : 마지막 원소(역방향)
- rend() : 첫 원소 이전 위치(역방향)
- *it : 현재 값 접근
- ++it : 다음 원소 이동
'TIL' 카테고리의 다른 글
| C++ < String > (0) | 2026.03.12 |
|---|---|
| C언어 <math.h> (0) | 2026.03.11 |
| C++ < Template(템플릿) > (0) | 2026.03.10 |
| C++ < 자원 관리(스택 메모리, 힙 메모리, 스마트 포인터) > (0) | 2026.03.09 |
| 코딩테스트 연습문제 <프로그래머스 - 자릿수 더하기, 약수 더하기 > (1) | 2026.03.09 |