(전체가 아니라 C#과 차이가 있는 부분을 중심으로 요약 정리)

컨테이너 개요

표준 라이브러리를 이용하면 표준 C 스타일 배열ㅇㄹ 사용하거나 연결 리스트나 스택 등을 직접 구현할 필요가 없다.

표준 라이브러리는 16가지 컨테이너를 제공하며 크게 네 가지 범주로 나눌 수 있다.

원소에 대한 요구사항

표준 라이브러리 컨테이너는 원소를 값으로 처리한다. (값 전달 방식, value semantics) 다시 말해 원소의 복제본을 저장하고, 대입 연산자로 대입하고 소멸자로 원소를 샂게한다. 그래서 표준 라이브러리를 사용하는 클래스를 작성할 때는 반드시 복제할 수 있게 (copyable) 만들어야 한다. 표준 라이브러리 컨테이너에서 원소를 요청하면 저장된 복제본에 대한 레퍼런스를 리턴한다.

원소를 레퍼런스로 처리하고 싶다면(레퍼런스 전달 방식, reference semantics) 원소를 그대로 넣지 않고 원소에 대한 포인터를 저장한다. 그러면 컨테이너에서 복제하는 대상이 포인터지만 복제된 값도 결국 똑같은 원소를 가리킨다. 아니면 컨테이너에 std::reference_wrapper를 저장해도 된다. reference_wrapper는 std::ref()나 std::cref()로 생성하며 결과로 나온 레퍼런스를 복제할 수 있게 만든다.

이동 전용(move-only) 타입, 즉 복제할 수 없는 (non-copyable) 타입도 컨테이너에 저장할 수 있지만 이때 컨테이너의 연산 중 일부는 컴파일 에러를 발생시킬 수 있다. 이동 전용 타입의 대표적인 예로 std::unique_ptr이 있다.

Caution) 컨테이너에 포인터를 저장하려면 unique_ptr나 shared_ptr을 사용한다. 포인터가 가리키는 객체의 소유자가 컨테이너라면 unique_ptr을 사용하고 컨테이너가 객체의 소유권을 다른 컨테이너와 공유한다면 shared_ptr을 사용한다.

표준 라이브러리 컨테이너에 대한 템플릿 타입 매개변수 중에는 할당자(allocator)라는 것이 있다. 컨테이너는 이 할당자를 이용하여 원소에 대한 메모리를 할당하거나 해제할 수 있다. 할당자 타입 매개변수는 디폴트 값이 정해져 있어서 거의 대부분 그냥 써도 된다.

map과 같은 일부 컨테이너는 템플릿 타입 매개변수로 비교자(comparator)도 받을 수 있다. 비교자는 원소를 정렬하는데 사용된다. 비교자도 디폴트 값이 정해져 있어서 매번 값을 지정할 필요가 없다.

디폴트 할당자와 비교자를 사용하는 컨테이너의 원소가 만족해야 할 요구사항은 다음과 같다.

제목 없음

Caution) 표준 라이브러리 컨테이너는 원소의 복제 생성자와 복제 대입 연산자를 호출하는 일이 많다. 따라서 두 연산자를 최대한 효율적으로 구현해야 한다. 원소에 대해 이동 의미론을 구현하는 것도 성능을 높이는데 도움 된다.

익셉션과 에러 검사

표준 라이브러리 컨테이너는 에러 검사 기능을 제공한다. 클라이언트는 이 기능으로 컨테이너 동작의 정확성을 보장할 수 있다고 기대하겠지만, 컨테이너 메서드나 함수 중 일부는 인덱스 범위를 벗어날 떄와 같은 특정한 조건에서 익셉션을 던지기도 한다.