C++

표준 라이브러리 둘러보기

Awesome Red Tomato 2022. 1. 3. 22:32

C++ 프로그래머에게 가장 중요한 라이브러리는 C++ 표준 라이브러리다. 이 라이브러리 중 가장 핵심은 제네릭 컨테이너와 제네릭 알고리즘이다. 이 라이브러리는 원래 표준 템플릿 라이브러리라는 이름의 서드파티 라이브러리였다. 그래서 STL이라고 많이 부른다. 하지만 STL은 C++ 표준 용어가 아니다. 따라서 이 책은 STL이란 용어를 사용하지 않는다.

 

1. 코드 작성법

표준 라이브러리는 C++의 템플릿과 연산자 오버로딩 기능을 상당히 많이 사용한다.

 

2. C++ 표준 라이브러리 둘러보기

2.1 스트링

C++은 string 클래스를 기본으로 제공한다. 메모리 관리 뿐 아니라 인덱스 경계 검사, 대입과 비교, 추출, 부분화, 치환 등 다양한 기능을 제공한다.

 

C++은 유니코드와 현지화도 지원한다. 그래서 다양한 언어(한국어 등)를 다루는 프로그램을 작성할 수 있다. <locale>에 정의된 Locale 클래스를 이용하면 숫자나 날짜를 특정 국가, 지역에 맞게 표현 가능하다. 19장에서 자세히 설명한다.

2.1 정규표현식

정규표현식은 <regex> 헤더에 정의되어 있다. 이 기능을 활용하면 텍스트를 다룰 때 흔히 사용하는 패턴 매칭을 쉽게 구현할 수 있다. 19장에서 자세히 설명한다.

2.3 I/O 스트림

C++은 스트림이라 부르는 입추력에 관한 모델을 제공한다. 세부 기능은 13장에서 설명했다.

2.4 스마트 포인터

프로그램 구현 중 생기는 오류는 다양하다. 우선 객체를 삭제하지 못하면 메모리 누수 현상이 발생한다. 또는 참조한 곳을 해제하여 포인터가 잘못된 곳을 가리키는 댕글링 포인터가 되는 현상도 있다. 또 다른 문제로 서로 다른 지점에서 동시에 공간을 해제하는 이중 해제가 있다.

 

C++은 이런 문제들을 방지하기 위해

  • unique_ptr
  • shared_ptr
  • weak_ptr
  • auto_ptr(C++11 이후 사용하지 않는다.)

과 같은 스마트 포인터를 제공한다.세부 기능은 7장에서 설명했다.

2.5 익셉션

C++은 익셉션 메커니즘을 제공한다. 함수나 메서드에서 발생한 다양한 종류의 에러를 상위 함수나 메서드로 전달할 수 있다. 익셉션 관련 기능은 <exception>, <stdexcept>, <system_error> 헤더 파일에 정의되어 있다. 세부 기능은 14장에서 설명했다.

2.6 수학 연산 관련 유틸리티

C++ 표준 라이브러리는 수학 연산에 관련된 다양한 클래스와 함수를 제공한다. abs(), remainder(), fma(), log(), pow(), sqrt(), sin() 등 흔히 사용되는 수학 연산들을 제공한다.

 

C++17부터는 르장드르 다항식, 베타 함수, 타원 적분, 베셀 함수, 노이만 함수와 같은 특수한 수학 함수도 추가됐다. 또한 complex란 이름의 클래스도 <complex> 헤더에 정의되어 있다.

 

컴파일 시간 유리수 연산 라이브러리는 ratio 클래스 템플릿을 제공한다. 이 클래스는 <ratio> 헤더에 정의되어 있다.

 

vector와 비슷하지만 고성능 수치 연산용으로 최적화한 valarray란 클래스도 제공한다. 이 클래스는 <ratio> 헤더에 정의되어 있다.

2.7 시간 관련 유틸리티

C++11 이후 srand(), rand() 기초적인 수준의 난수 생성기 외에 훨씬 강력한 무작위수 라이브러리가 추가되었다.

<random> 헤더에 정의되어 있으며 무작위수 엔진, 무작위수 엔진 어댑터, 무작위수 분포 등을 제공한다. 20장에서 자세히 설명한다.

2.9 이니셜라이즈 리스트

이니셜라이즈 리스트는 <initializer_list> 헤더에 정의되어 있다. 이를 활용하면 인수의 개수가 다양한 함수를 쉽게 작성할 수 있다. 1장에서 설명했다.

2.10 pair와 tuple

<utility> 헤더에서 서로 다른 타입의 두 원소를 하나로 묶어 저장하는 pair 템플릿을 정의하고 있다. 이러한 저장 방식을 이종 원소 저장이라 부른다. 이 장에서는 모두 원소 저장 방식을 따른다. 17장에서 자세히 설명한다.

 

<tuple> 헤더에 정의된 튜플은 pair를 일반화한 것이다. 고정된 크기의 수열로 서로 다른 타입의 원소를 저장할 수 있다. 20장에서 자세히 설명한다.

2.11 optional, variant, any

C++17에 추가되었다.

  • optional: <optional> 헤더에 정의되어 있다. 특정한 타입의 값을 저장하거나 값을 가지지 않을 수 있다. 값이 없을 수도 있는 함수의 매개변수나 리턴 타입으로 사용할 수 있다.
  • variant: <variant> 헤더에 정의되어 있다. 지정한 타입 집합 중 하나의 값을 가지거나 가지지 않을 수 있다.
  • any: <any> 헤더에 정의되어 있다. 모든 타입의 값을 단 하나만 가진다.

20장에서 자세히 설명한다.

2.12 함수 객체

함수 호출 연산자를 구현하는 클래스를 함수 객체(펑터, functor)라 부른다. <functional> 헤더에 정의되어 있다. 함수 객체는 특정한 표준 라이브러리 알고리즘에 대한 조건식 등에 활용된다. 기존 함수 객체를 바탕으로 함수 객체를 새로 생성하는 기능도 제공한다. 18장에서 자세히 설명한다.

2.13 파일 시스템

C++17에 추가되었다. <filesystem> 헤더에 정의되어 있는 것들은 모두 std::filesystem 네임스페이스에 속한다. 이 라이브러리는 디렉터리나 파일을 조회하거나, 디렉터리에 담긴 항목에 대해 반복문을 수행하거나, 경로를 다루거나, 파일 크기, 확장자, 생성 시각 등과 같은 파일에 대한 정보를 조회하는 기능을 제공한다. 20장에서 자세히 설명한다.

2.14 멀티스레딩

멀티스레딩을 지원하는데 다양한 기능을 제공한다. <thread> 헤더에 정의된 thread 클래스를 이용하면 스레드를 하나씩 생성할 수 있다.

 

멀티 스레드를 작성할 때 여러 스래드가 같은 데이터를 읽고 쓰지 않도록 주의해야 한다. <atomic> 헤더에 정의된 atomic을 사용하면 데이터를 스테드에 안전하고 아토믹하게(여러 스레드가 동시 접근하지 않게) 만들 수 있다. <condition_variable>과 <mutex> 헤더에서도 다양한 스레드 동기화 메커니즘을 제공한다. 23장에서 자세히 설명한다.

2.15 타입 트레이트

타입 트레이트(타입 특성/속성) 기능은 <type_traits> 헤더에 정의되어 있으며, 컴파일 시간에 타입 정보를 조회할 수 있다. 이 기능은 고급 템플릿을 작성할 때 유용하다. 22장에서 자세히 설명한다.

2.16 표준 정수 타입

<cstdint> 헤더에서는 다양한 표준 정수 타입<int8_t, int64_t> 등을 정의하고 있다. 30장에서 자세히 설명한다.

2.17 컨테이너

표준 라이브러리는 링크드 리스트나 큐와 같이 흔히 사용되는 데이터 구조를 제공한다. 

  • vector
    <vector>에 정의되어 있다. 일련의 원소를 저장하고 각 원소를 임의 접근 가능하다(인덱스 접근 가능 vec[0]). 배열과 마찬가지로 메모리 공간에 연달아 저장된다. 동적 배열로 원소 수에 따라 크기가 자동으로 늘거나 줄어든다.

  • list
    리스트는 양방향 연결 리스트로서 <list>에 정의되어 있다. vector와는 달리 연속된 메모리 공간에 저장하지 않는다. list의 원소마다 앞과 뒤에 원소에 대한 정보(주로 포인터)가 정의되어 있다. 연산 수행할 때 위치를 정확하게 알고 있다면 vector보다 빠르다.

  • deque
    양방향 큐의 줄임말로 <deque> 헤더에 정의되어 있다.

  • array
    <array> 헤더에 정의되어 있다. 주어진 컨테이너에 담긴 원소 개수를 정확하게 알고 있고, vector나 list처럼 공간을 동적으로 늘리는 유연성이 필요 없다면 크기가 고정된 array를 사용하는 것이 좋다.

  • queue
    큐는 FIFO(선입선출, first in first out) 방식으로 작동한다. <queue> 헤더에 정의되어 있다.

  • priority_queue
    큐와 달리 원소마다 우선순위가 정해진 큐를 제공한다.

  • stack
    LIFO(후입선출, last in first out) 동작을 구현한 것이다. <stack> 헤더에 정의되어 있다. 

  • set과 multiset
    set은 <set> 헤더에 정의된 클래스 탬플릿으로, 원소들의 집합을 표현한 것이다. 수학의 집합과 같이 원소가 중복될 수 없고 원소의 인스턴스가 최소 한 개 이상 있어야 한다. set에 중복된 원소를 추가하려면 multiset을 사용하면 된다.

  • map과 multimap
    map은 <map>에 정의된 클래스 탬플릿으로, 연관 배열을 표현한 것이다. map을 이용하면 모든 타입으로 인덱스를 표현할 수 있는 배열을 만들 수 있다. map은 키(key)/값(value) 쌍으로 저장한다.

  • 비정렬 연결 컨테이너와 해시 테이블표준 라이브러리는 다음과 같은 네 종류의 해시 테이블을 제공한다.
    - unordered_map
    - unordered_multimap
    - unordered_set
    - unordered_multiset
    <unordered_map>, <unordered_set>에 정의되어 있다. 비정렬 연관 컨테이너의 동작은 정렬 버전과 비슷하다. 17장에서 자세히 설명한다.

  • bitset
    프로그램을 작성할 때 int나 long 값 하나를 비트 단위로 구분해 플래그 집합을 표현하는 개발자가 많다. 각 비트를 읽거나 설정할 때는 비트 연산자를 이용한다. C++ 표준 라이브러리는 이렇게 비트 단위로 다루는 작업을 추상화한 bitset 클래스를 제공한다. 따라서 비트 연산을 일일히 처리하지 않아도 된다

    우리가 흔히 아는 컨테이너와 달리 bitset은 크기가 고정돼있으며 반복자를 제공하지 않고, 원소를 추가하거나 삭제할 수 없다. bitset<N>은 N비트만큼 공간을 할당한 것이다.

2.18 알고리즘

작성예정

'C++' 카테고리의 다른 글

(C++11) shared_ptr, enable_shared_from_this  (0) 2022.04.28
컨테이너와 반복자 살펴보기  (0) 2022.01.03
I/O 완전 분석  (0) 2022.01.01