19 분 소요

std::vector<T> 컨테이너

  • 크기가 동적인 배열이다.
  • 컨테이너 끝에서 원소를 추가/삭제 할 때 효율적이다.
  • Random Access를 제공한다.

0. capacity와 size

  • capacity(용량, vector<T>::size_type): 메모리를 추가 할당하지 않아도 저장할 수 있는 원소들의 개수
  • size(크기, vector<T>::size_type): 실제로 갖고 있는 원소들의 개수
    vec.reserve(n);     // capacity를 n으로 설정
    // vec의 capacity가 n보다 크거나 같다면(<=) 변화 없다.
    // capacity가 증가하면 주소가 바뀌었기 때문에 기존의 iterator는 무효화된다.
    // capacity는 log증가 알고리즘을 사용한다.
    

1. 생성하기

#include <vector>
std::vector<T> vec;                 // 선언 (capacity:0, size:0)
// vec의 첫 번째 데이터를 추가할 때 메모리가 할당된다.

std::vector<T> vec(n);              // 0으로 초기화된 원소 n개 생성
std::vector<T> vec(n, t);           // t로 초기화된 원소 n개 생성
std::vector<T> vec {t1, t2, t3};    // t1, t2, t3로 초기화된 벡터 생성 (capacity:3, size:3)

std::array<T, 5> arr {t1, t2, t3, t4, t5};
std::vector<T> copy_vec {std::begin(arr), std::end(arr)};    // array를 복사하여 생성
std::vector<T> move_vec {make_move_iterator(std::begin(arr)), make_move_iterator(std::end(arr))};                // array를 이동하여 생성(이동 반복자)
생성하기 테스트 🔍
  1. vec.capacity(), vec.size()의 관계
    size: 0, capacity: 0    // 생성
    size: 1, capacity: 1
    size: 2, capacity: 2
    size: 3, capacity: 3
    size: 4, capacity: 4
    size: 5, capacity: 6
    size: 6, capacity: 6
    size: 7, capacity: 9
    size: 8, capacity: 9
    size: 9, capacity: 9
    size: 10, capacity: 13
    size: 11, capacity: 13
    size: 12, capacity: 13
    size: 13, capacity: 13
    size: 14, capacity: 19
    size: 15, capacity: 19
    size: 16, capacity: 19
    size: 17, capacity: 19
    size: 18, capacity: 19
    size: 19, capacity: 19
    size: 20, capacity: 28
    size: 21, capacity: 28
    size: 22, capacity: 28
    size: 23, capacity: 28
    size: 24, capacity: 28
    size: 25, capacity: 28
    size: 26, capacity: 28
    size: 27, capacity: 28
    size: 28, capacity: 28
    size: 29, capacity: 42
    size: 30, capacity: 42
    size: 31, capacity: 42
    size: 32, capacity: 42
    size: 33, capacity: 42
    size: 34, capacity: 42
    size: 35, capacity: 42
    size: 36, capacity: 42
    size: 37, capacity: 42
    size: 38, capacity: 42
    size: 39, capacity: 42
    size: 40, capacity: 42
    size: 41, capacity: 42
    size: 42, capacity: 42
    size: 43, capacity: 63
    size: 44, capacity: 63
    size: 45, capacity: 63
    size: 46, capacity: 63
    size: 47, capacity: 63
    size: 48, capacity: 63
    size: 49, capacity: 63
    size: 50, capacity: 63
    
  2. make_move_iterator
    (/* 공부 후 추가*/)
    


2. 접근하기

T front = vec.front();  // 첫 번째 원소의 참조값
T back = vec.back();    // 마지막 원소의 참조값
T value = vec[index];   // index의 원소의 참조값
T* data = vec.data();   // 원소를 저장하는 배열에 대한 포인터


3. 반복자(Iterator)

#include <iterator>
// 1. input
std::copy(std::istream_iterator<T>(std::cin), std::istream_iterator<T>(), std::back_iterator(vec));
// 2. output
std::copy(std::begin(vec), std::end(vec), std::ostream_iterator<T>(std::cout, " "));


4. 원소 삽입하기

// 맨 뒤에 객체(t) 삽입
vec.push_back(t);       // 객제(t)를 별도로 생성하여 인수도 전달 (추가 이동연산 필요, r-value 참조)
vec.emplace_back(t);    // 내부에서 객체(t)를 바로 생성 (내부에 생성자로 생성, push_back보다 효율적이다.)
  • vector는 끝이 아닌 위치에 값을 삽입하는 모든 작업은 부하가 있다.
vec.emplace(삽입위치 iter, t);  // 원하는 위치에 객체(t)를 삽입
vec.insert(삽입위치 iter, t);   // 원하는 위치에 객체(t)를 삽입

T t_arr[] {t1, t2, t3, t4};
vec.insert(삽입위치 iter, std::begin(t_arr), std::end(t_arr));  // 순차열 삽입

vec.insert(삽입위치 iter, count, t);            // t를 count개 만큼 삽입
vec.insert(삽입위치 iter, {t1, t2, t3, t4});    // 초기화 리스트로 삽입


5. 원소 삭제하기

vec.clear();    // 원소 전체 삭제 (size:0, capacity:그대로)
vec.pop_back(); // 마지막 원소 삭제
// 중간의 원소 삭제
std::swap(삭제원소 iter, std::end(vec)-1);
vec.pop_back();
vec.erase(삭제위치 iter);                   // 원하는 위치의 객체 삭제 
vec.erase(시작위치 iter, +1위치 iter);    // 원하는 범위의 객체 삭제

// erase-remove idiom
auto iter = std::remove(std::begin(vec), std::end(vec). t); // vec에서 t와 같은 원소 삭제
vec.erase(iter, std::end(vec)); // 잉여 원소 삭제 (remove에서 삭제된 객체는 빈 객체로 존재한다.)
vec.shrink_to_fit();    // 원소에 필요한 만큼 capacity를 줄인다. (이전 반복자는 무효화 된다.)


카테고리:

업데이트:

댓글남기기