컨테이너 기본

  • 컨테이너는 member type을 정의해야 함

    • 예: size_typeusing size_type = std::size_t로 정의
  • 대부분의 멤버 함수는 반환과 제거를 동시에 하지 않음

    • 예외 안정성과 참조 반환을 위해 분리
    • v.back()v.pop_back() 구분됨
  • 단위 전략 디자인 많이 사용

    • 예: allocator, compare, hash 전달 가능

sequence container

  • vector는 앞쪽 삽입/삭제 불가능
  • [] 연산은 vector, deque, array만 지원

vector

Capacity

  • resize(10)resize(7) 해도 메모리는 유지됨
  • size: 요소 개수, capacity: 실제 메모리 크기
  • shrink_to_fit: 새 메모리를 할당하고 복사함으로써 capacity 줄임

push_back 성능

  • capacity > size일 경우 빠름
  • 아니면 메모리 재할당 발생으로 느려짐

reserve

  • capacity만 미리 확보, 생성자는 호출되지 않음
  • resize, push_back 호출 시 생성자 호출됨

복사 / 이동 / 삭제

  • 복사: size만큼만 복사
  • move: 메모리를 그대로 이송함으로써 size, capacity 그대로 이동
  • clear: capacity 유지
  • shrink_to_fit: capacity 제거
  • capacity는 연속된 메모리 사용 컨테이너만 가짐

emplace

목적

  • 객체를 컨테이너에 복사하지 않고 직접 생성자 인자를 전달하여 생성

예제

  class Point {
public:
  explicit Point(int a) {}
  Point(int a, int b) {}
  Point(const Point&) {}
};

v.emplace_back(1, 2);     // Point(int, int)
Point pt(1, 2);
v.emplace_back(pt);      // Point(const Point&)
v.emplace_back(1);       // Point(int)
  

원리

  template<typename ...ARGS>
deprecated(atuo) emplace_back(ARGS&& ...args) {
  new T(std::forward<ARGS>(args)...);
}
  
  • 사용자 정의 타입에 유리
  • primitive type은 push_back, emplace_back 유사함

array

  • C++11부터 지원
  • 모든 요소를 스택에 저장
  • 배열과 벡터는 계속 생성 파괴를 반복하는 상황에서 속도 차이가 매우 많이남
  • push, pop, resize 불가
  std::array<int, 5> a{1, 2, 3, 4, 5};
  

move와 array

  • 요소 타입이 move를 지원하지 않으면 복사 동작과 동일
  • int: 복사와 동일
  • string: move 수행
  • vector와 달리 array는 메모리를 가져가지 않음

Container Adapter: stack, queue, priority_queue

  • 반복자 없음
  • 내부에 컨테이너를 포함하는 adapter 패턴

stack

  • 내부 컨테이너: list, vector, deque

queue

  • 내부 컨테이너: list, deque (앞뒤 필요)
  • vector는 불가

priority_queue

  • 내부 컨테이너: vector, deque
  • random access iterator 필요

set

특징

  • 요소 수정 불가하나 반복자는 꺼낼 수 있음

  • bidirectional iterator 지원

  • findcontains

    • contains: C++20부터 지원, bool 반환
    • find: 반복자 반환 후 비교

사용자 정의 타입 사용

방법 1: 비교 함수 객체 전달
방법 2: 클래스 내부에 비교 연산자 정의
방법 3: std::less specialization
  template<>
class std::less<People> {
public:
  bool operator()(const People& p1, const People& p2) const {
    return p1.id < p2.id;
  }
};
  
  • std namespace에 직접 타입 추가는 표준 위반이지만 specialization은 허용됨