치춘짱베리굿나이스

[Rank 5] ft_containers - std::vector 본문

42/42s Cursus

[Rank 5] ft_containers - std::vector

치춘 2023. 2. 4. 15:55

Vector

는 무엇인가

#include <vector>

int main(void) {
    std::vector<int> vect1; // 정수형 컨테이너, 용량 0으로 초기화
    std::vector<std::string> vect2(5); // 문자열 컨테이너, 용량 5로 초기화
}

이전에 우리가 C에서 사용하던 배열은 고정된 길이만큼만 선언 및 할당해 놓고 그 제한 안에서 사용하는 형태의 컨테이너였다

벡터는 거기에서 한 단계 더 나아가, 원소를 추가할 때마다 이전에 할당한 용량이 부족하다면 → 메모리를 재할당하여 용량을 자동으로 늘려주는 신기한 컨테이너다

그 말인 즉슨, 처음에 벡터를 선언할 때 원소의 개수가 몇 개 들어올 지 모른다면 그냥 0개로 초기화해 주어도 원소를 추가할 때마다 알아서 메모리를 새롭게 할당한다는 뜻이다

더이상 내가 malloc 하고 free를 반복할 필요가 없다 (물론 C++에서는 newdelete 겠지만…)

템플릿 클래스로 선언되어 있으므로 원하는 자료형을 담은 벡터 컨테이너를 선언할 수 있다

장점

  • 배열과 달리, 총 용량을 생각할 필요가 없다
    • 넣을 때는 알아서 용량을 늘려주고, 필요없는 용량은 shrink_to_fit (C++11부터) 을 통해 해제시킬 수도 있다
    • 초기화할 때도 배열 크기를 굳이 넣어줄 필요가 없다 (0으로 초기화해도 요소를 추가할 때마다 늘어나므로)
  • 순차 컨테이너이므로 랜덤 접근 (임의의 위치를 참조하여 요소를 가져오는 것) 이 가능하다
    • 사용자가 특정 위치의 요소를 고의로 조작하지 않는 이상, 요소의 순서는 변함이 없으므로 인덱스만 알고 있다면 언제든지 접근이 가능하다
  • 벡터의 맨 뒤에 요소를 추가하거나, 맨 뒤 요소를 삭제하는 연산은 복잡도가 O(1) 로 매우 싸다
    • 맨 뒤에 요소를 쉽게 추가하고 삭제할 수 있다는 특성 덕에, std::stack (스택) 컨테이너를 구현할 때 베이스 컨테이너로 이용하는 경우가 종종 있다

단점

  • 맨 뒤 요소를 조작하는 데에는 시간 복잡도가 크지 않지만, 중간에 위치한 요소를 삭제하거나 중간에 요소를 끼워넣는 동작은 시간 복잡도가 상당히 크다
    • 용량이 부족하면 새로 메모리를 할당하고 기존의 내용물을 전부 복사해야 하기 때문에 최악의 경우 O(n) 까지 소모된다
    • 배열 기반의 컨테이너 특성상 어쩔 수 없다 ,,

Sequence Container

std::vector<std::string> ft_transcendence =

┏━━━━━━━━━┳━━━━━━━━━━┳━━━━━━━━┳━━━━━┳━━━━━━━━━━┳━━━━━━┳━━━━━━━┳━━━━━━┓
┃ jiychoi ┃ junmkang ┃ jasong ┃ san ┃ jisokang ┃ ycha ┃ incho ┃ hena ┃ 
┗━━━━━━━━━┻━━━━━━━━━━┻━━━━━━━━┻━━━━━┻━━━━━━━━━━┻━━━━━━┻━━━━━━━┻━━━━━━┛

순차적인, 연속적인 이라는 의미의 Sequence (시퀀스) 에서도 알 수 있듯이, Sequence Container (순차 컨테이너) 는 데이터를 순차적으로 저장하며, 한번 저장한 데이터의 순서가 (내가 임의로 조작하지 않는 이상) 계속 유지된다

  • 컨테이너 내의 요소들이 선형적으로 저장되어 있어야 한다
    • Map, Set 등과 같이 부모 노드로 올라갔다가 자식 노드로 내려갔다 등등을 하면 안 된다
    • 한 요소의 앞뒤로 다른 요소가 존재해야 한다는 뜻 (맨 앞, 맨 뒤 제외)
  • 내부적으로 사용되는 반복자는 최소 순방향 반복자 이상의 특징을 모두 띄어야 한다
    • 반복자는 서로 어느 정도 포함 관계를 가진다
    • 순방향 반복자의 특징을 포함하는 반복자는 순방향, 양방향, 랜덤 액세스, 그리고 C++20에서 소개된 연속 (contiguous) 반복자가 있다
    • 순방향 반복자의 특징을 포함해야 한다는 것은, 반복자가 이동할 때마다 접근하는 요소의 순서를 보장해 주어야 한다는 뜻이다
  • 요소의 순서가 보장되므로, 특정 위치를 참조했을 때 항상 같은 요소가 반환되어야 한다
    • 그렇다는 것은, 2번 인덱스나 6번 인덱스 등 특정 인덱스를 참조하는 연산자가 구현되어 있어야 한다는 뜻이다
    • 또한 ++, --, +, - 등 위치를 연산하는 연산자 오버로드가 존재해야 한다

크기 (size) 와 용량 (capacity)

쉬운 비교 (?) 를 위해 2013년에 찍어놨던 마비노기 스크린샷을 가져왔다

벡터의 크기 (size) 는 벡터에 실제로 저장된 요소의 개수이다

벡터의 용량 (capacity) 는 벡터에서 할당된 메모리 공간의 총 크기이다

용량 ≠ 크기 로, 용량은 항상 크기보다 크거나 같다

만약 새로운 요소를 추가하려 하는데 용량이 부족하다면 새로운 공간을 할당하고 용량을 늘린다 (size, capacity 모두 증가)

새로운 요소를 추가할 때 이미 충분한 용량이 있다면, 용량을 늘리지 않고 요소만 채워넣는다 (size만 증가)

템플릿 인자

template < typename T, class Allocator = std::allocator<T> >

T

벡터 내부에 저장될 요소의 자료형이다 (= int, char, std::string 등이 올 수 있다는 뜻)

후술할 멤버 타입으로 value_type에 alias 되어 있기도 하다

Allocator

메모리 할당에 사용되는 할당자 객체의 유형이다

기본적으로 std::allocator<T> 가 지정되며, 더 효율적인 메모리 할당 객체가 있다면 두 번째 인자로 넣어 적절히 사용하면 된다

std::allocator<T> 가 기본형인 데에서 알 수 있듯, T 자료형 크기만큼의 메모리를 조작할 때 사용된다

후술할 멤버 자료형으로 allocator_type에 alias 되어 있기도 하다

멤버 자료형 정의

value_type

템플릿 인자로 들어오는 T 의 alias 이다

allocator_type

템플릿 인자로 들어오는 Allocator 의 alias 이다

size_type

할당자 객체의 내부에서 사용되는 size_type 의 alias 이다

부호 없는 정수형으로, 할당자가 할당하는 메모리 포인터의 단위를 나타낸다

difference_type

할당자 객체의 내부에서 사용되는 difference_type 의 alias 이다

부호 있는 정수형으로, 할당자가 할당하는 메모리 주소 간 차이를 나타낸다

reference, const_reference

할당자 객체의 내부에서 사용되는 reference, const_reference 의 alias 이다

할당자가 할당한 메모리를 참조할 때에 사용하는 자료형이다

pointer, const_pointer

할당자 객체의 내부에서 사용되는 pointer, const_pointer 의 alias 이다

할당자가 할당한 메모리의 주소를 나타내는 자료형이다

iterator, const_iterator

컨테이너를 순회할 때 이용하는 반복자의 자료형이다

벡터의 경우, 요소의 순서가 고정되어 선형적으로 순회가 가능해야 하고, 특정 위치에 임의 접근이 가능하다

따라서 순방향 반복자의 특징을 띄면서 임의 접근을 가능케 하는 임의 접근 반복자 (random access iterator) 를 사용한다

reverse_iterator, const_reverse_iterator

컨테이너를 역방향으로 순회할 때 이용하는 반복자의 자료형이다

iterator, const_iterator 를 기초로 하여 구현한다

멤버 변수

내부 구현을 어떻게 하느냐에 따라 조금씩 달라질 수 있다

_allocator

벡터 내부적으로 메모리를 할당할 때에 사용하는 할당자이다

생성자에서 인자로 받아 멤버 변수로 저장하는데, 대개 기본값으로 std::allocator 를 사용하므로 크게 신경쓸 필요가 없다 (메모리 효율을 높일 것이 아니라면 기본값을 사용해도 지장 없다는 뜻)

allocator 로 메모리 할당하는 방법 정도만 알아두자

_base_pointer

할당자로 할당한 메모리의 첫 번째 요소 주소를 나타낸다

생성자 단계에서 할당자를 통해 메모리를 할당받고, 그 시작점을 저장하는 용도로 사용한다

연산자 오버로드 등은 _base_pointer 를 이용하면 매우 쉽게 구현할 수 있다

_size

벡터의 크기이다

용량 (capacity) 과는 다르다!!!

_capacity

벡터의 용량이다 (위에서 설명)

멤버 함수 - 생성자와 소멸자

기본 생성자 (default constructor)

explicit vector (const allocator_type& alloc = allocator_type());
  • 아무 인자도 넣지 않은 기본 중의 기본 생성자이다
  • 원한다면 할당자를 두 번째 인자 (alloc) 로 넘겨도 되지만, 기본적으로 allocator_type 으로 alias 한 할당자가 들어가므로 다른 할당자를 사용할 것이 아니라면 무시해도 좋다

채움 생성자 (fill constructor)

explicit vector (size_type n, const value_type& val = value_type(), const allocator_type& alloc = allocator_type());
  • n개만큼의 공간을 할당하고, val로 초기화한다
  • val은 기본적으로 value_type 의 기본 생성자를 호출하므로, 특정 값으로 채우지 않을 것이라면 비워주어도 상관 없다
  • alloc 또한 기본 생성자와 마찬가지로 기본값이 들어가므로 무시해도 된다
  • 이름이 맞게 번역한 건진 모르겠는데 다른 생성자들이랑 이름을 통일하고 싶어서… 임의로 지어냈다

 

std::vector<int> vect(5);
std::vector<int> vect(7, 10);
  • 위와 같은 방식으로 선언하는 경우가 fill 생성자의 용례라고 볼 수 있겠다

범위 생성자 (range constructor)

template <class InputIterator>
vector (InputIterator first, InputIterator last, const allocator_type& alloc = allocator_type());
  • 반복자 2개 (시작점, 끝점) 를 인자로 받으며, 해당 범위 내의 모든 요소를 순서대로 복사하여 새로운 벡터를 초기화한다
  • 기존 반복자가 가리키는 요소들의 순서와 새로운 벡터의 요소 순서는 같다

복사 생성자 (copy constructor)

vector (const vector& instance);
  • 기존의 벡터를 인자로 받고, 내용물을 그대로 복사해서 새로운 벡터를 생성한다
  • 기존 벡터의 요소 순서와 새로운 벡터의 요소 순서는 같다

멤버 함수 - 대입 연산자 오버로드

operator=

vector& operator= (const vector& instance);
  • = 연산자의 오버로드로, 우측에 있는 벡터를 좌측의 벡터에 그대로 복사한다
  • 우측 벡터의 모든 요소와 멤버 변수들이 순서대로 복사되며, 좌측 벡터의 기존 요소들은 소멸하거나 복사 대입 연산자에 정의된 대로 동작한다

멤버 함수 - 반복자 관련

begin

iterator begin ();
const_iterator begin (); // const 오버로드
  • 벡터의 맨 앞을 가리키는 반복자를 반환한다
  • vector::front 메서드는 첫 번째 요소의 참조를 반환하고, vector::begin은 첫 번째 요소의 반복자 (random access iterator) 를 반환한다는 점에서 다르다
  • const_iterator 타입의 begin()const 요소에 대한 반복자를 반환한다

end

iterator end ();
const_iterator end (); // const 오버로드
  • 벡터의 맨 끝 요소의 다음 칸 (cplusplus 에서는 past-the-end 라고 표현) 을 가리키는 반복자를 반환한다
    • 맨 끝 요소가 아니다!!!!
  • 벡터가 비어 있을 경우, vector::begin()vector::end() 함수는 같은 반복자를 반환한다
  • const_iterator 타입의 end()const 요소에 대한 반복자를 반환한다

rbegin

reverse_iterator rbegin ();
const_reverse_iterator rbegin ();
  • 벡터의 맨 끝 요소를 가리키는 역방향 반복자 (reverse iterator) 를 반환한다
    • 맨 처음 요소가 아니다!!!
    • 역방향 반복자이기 때문에, 가장 뒤에 있는 요소가 시작점이 되어 거꾸로 움직인다
  • const_reverse_iterator 타입의 rbegin()const 요소에 대한 반복자를 반환한다

rend

reverse_iterator rend ();
const_reverse_iterator rend ();
  • 벡터의 맨 처음 요소의 이전 칸을 가리키는 역방향 반복자를 반환한다
  • const_reverse_iterator 타입의 rend()const 요소에 대한 반복자를 반환한다

멤버 함수 - 용량 관련

size

size_type size () const;
  • 벡터 안에 들어있는 원소의 개수 (크기) 를 반환한다
  • 실제로 벡터가 갖고 있는 원소의 개수를 나타내며, capacity는 벡터의 총 용량 (가용 공간 + 요소가 들어있는 공간) 이므로 size와는 다르다

max_size

size_type max_size () const;
  • 벡터가 가질 수 있는 최대 원소 개수를 반환한다
  • 현재 벡터의 size / capacity와 관계없이, 시스템적으로 제한된 개수를 반환한다
  • 컨테이너가 max_size 만큼의 메모리를 할당받을 수 있다는 보장은 없다
    • 중간에 실패할 수도 있다는 뜻

resize

void resize (size_type n, value_type val = value_type());
  • 벡터의 크기를 n만큼 재조정한다
    • 크기를 재조정한다는 것은, 벡터가 n개의 원소를 가지고 있을 수 있도록 기존의 원소들을 제거하거나, 새로운 원소를 추가한다는 뜻이다
    • n이 현재 벡터의 size보다 클 경우, n - size개만큼의 원소를 채워넣는다
    • n이 현재 벡터의 size보다 작을 경우,

capacity

size_type capacity () const;
  • 현재 벡터에 할당된 총 용량을 반환한다
  • size_type는 어차피 unsigned int가 래핑된 형태이므로 양의 정수를 반환한다고 생각하면 된다
  • capacitysize와 같을 필요가 없다
    • size > capacity 는 불가능하지만 sizecapacity 는 가능하다
    • capacitysize의 최대 상한치를 나타내는 것 또한 아니며, sizecapacity만큼 꽉 찼을 경우 벡터는 자동으로 추가적인 공간을 할당해서 capacity를 늘린다
    • 물론 max_size() 의 반환값보다 큰 용량을 할당받을 수는 없다

empty

bool empty () const;
  • 현재 벡터가 비어 있는지 여부를 boolean으로 반환한다
    • 요소가 하나라도 있으면 false, 하나도 없다면 true
    • 대개 멤버 변수인 size 값을 이용하여 판단한다
  • 이름만 보면 컨테이너를 비우는 함수 같지만 컨테이너 내부 내용물은 건드리지 않는다
    • 컨테이너를 비우는 함수는 clear() 를 사용한다

reserve

void reserve (size_type n);
  • 최소한 n개의 요소를 담을 수 있을 정도로 컨테이너의 용량을 늘린다
    • 컨테이너의 용량을 늘린다는 것은 즉, 새로운 메모리를 할당하고 요소들을 다 해당 공간으로 옮긴다는 의미이다
    • 현재 용량이 n개의 요소를 담을 수 있을 정도로 충분하다면, 아무런 동작도 하지 않는다
  • 메모리 재할당을 통해 용량 (capacity) 과 base_pointer 는 수정되지만, 요소의 개수가 수정되는 것은 아니므로 크기 (size) 는 변하지 않는다

멤버 함수 - 요소 접근자 관련

operator[]

reference operator[] (size_type n);
const_reference operator[] (size_type n) const;
  • 벡터의 n번째 요소를 반환한다 (n은 0부터 시작)
    • nsize보다 클 경우 (현재 벡터의 개수를 넘어서는 인덱스에 접근할 경우) 예외 처리가 되지 않으며, undefined behavior으로 간주한다
    • 예외를 발생시키고 싶다면 at() 을 쓰는 것을 추천한다고 한다

at

reference at (size_type n);
const_reference at (size_type n) const;
  • 벡터의 n번째 요소를 반환한다 (n은 0부터 시작)
    • 내부적으로 n의 크기를 검사하며, nsize보다 클 경우 (현재 벡터의 개수를 넘어서는 인덱스에 접근할 경우) std::out_of_range 예외가 발생한다
    • [] 연산자 오버로드와 동일한 동작을 하지만 예외가 발생한다는 점이 다르다

front

reference front ();
const_reference front () const;
  • 벡터의 맨 앞 요소를 반환한다
    • begin() 함수와 다른 점은, begin() 은 맨 앞 요소를 가리키는 반복자를 반환하고 front() 는 참조를 반환한다는 것이다
  • 빈 벡터 (empty() = true) 의 front() 를 호출하는 것은 undefined behavior 으로 간주한다

back

reference back ();
const_reference back () const;
  • 벡터의 맨 뒤 요소를 반환한다
    • end() 함수와 다른 점은, end() 는 맨 뒤 요소의 다음 칸을 가리키는 반복자를 반환하고, back() 은 맨 뒤 요소의 참조를 반환한다는 것이다
    • end() 와 다르게, 맨 뒤 요소의 다음 칸을 반환하지 않는다!!! 해당 위치의 참조를 바로 반환한다!!!
  • 빈 벡터 (empty() = true) 의 end() 를 호출하는 것은 undefined behavior 으로 간주한다

멤버 함수 - 수정 관련

assign

template <class InputIterator>
void assign (InputIterator first, InputIterator last); // range
void assign (size_type n, const value_type& val); // fill
  • 벡터 내부의 기존 요소들을 날리고 새로운 요소들로 채워넣는다
    • 기존 요소들은 소멸된다 (소멸자가 호출된다는 뜻)
    • 현재 벡터의 용량이 새로운 요소의 개수보다 작을 경우엔 재할당이 이루어지지만, 그렇지 않을 경우에는 요소만 수정된다
  • InputIterator 반복자를 인자로 받는 오버로드 (범위 assign) 는 반복자가 가리키는 순서대로 요소가 초기화된다
    • 범위 생성자 (range constructor) 에서 InputIterator 인자들이 하는 역할과 동일하다
  • nval을 인자로 받는 오버로드는 valn개만큼 초기화된다

push_back

void push_back (const value_type& val);
  • 벡터의 맨 뒤에 요소 val을 추가한다
    • 요소가 1 늘어나면서 벡터의 크기 (size) 도 1 증가한다
    • 만약 용량이 부족하여 val을 추가할 수 없다면, 자동으로 재할당을 통해 용량을 증가시킨 후 val을 추가한다
    • 이 경우, 할당에 실패하면 allocator 내부적으로 선언된 예외가 throw 될 수 있다 (예를 들어, std::allocatorbad_alloc 예외를 던진다)

pop_back

void pop_back ();
  • 벡터의 맨 뒤 요소를 제거한다
    • 요소가 1 줄어들면서 벡터의 크기 (size) 도 1 감소한다
    • 요소가 삭제되면서 소멸자도 자동으로 호출된다

insert

iterator insert (iterator position, const value_type& val); // single
void insert (iterator position, size_type n, const value_type& val); // fill
template <class InputIterator>
void insert (iterator position, InputIterator first, InputIterator last); // range
  • 벡터의 특정 위치에 요소를 1개 이상 추가한다
    • 첫 번째 오버로드 (single) 는 position 위치에 단 하나의 요소 val을 추가한다
    • 두 번째 오버로드 (fill) 는 position 위치에 요소 valn개 추가한다
    • 세 번째 오버로드 (range) 는 position 위치에 first 반복자부터 last 반복자까지의 요소를 추가한다
  • 추가된 (삽입된) 요소의 개수만큼 벡터의 크기 (size) 가 늘어난다
  • 만약 용량이 부족할 경우 (공간이 부족할 경우) 공간을 새로 할당해 주므로, capacity 가 바뀔 가능성이 있다

 

{ 1, 2, 3, 4, 5 }

// 3 의 위치에 10 을 삽입하고 싶은 경우
// 3, 4, 5 를 뒤로 한 칸씩 민다
{ 1, 2,  , 3, 4, 5 }

// 밀고 확보된 공간에 요소를 삽입한다
{ 1, 2, 10, 3, 4, 5 }

// 4 의 위치에 11, 12, 13 을 삽입하고 싶은 경우
// 4, 5 를 뒤로 3칸 민다
{ 1, 2, 10, 3,  ,  ,  , 4, 5 }

// 밀고 확보된 공간에 요소를 삽입한다
{ 1, 2, 10, 3, 11, 12, 13, 4, 5 }
  • 벡터의 중간에 요소를 추가하기 위해 뒤에 올 요소를 밀고 공간을 확보한 다음, 해당 공간에 요소를 넣어준다
    • 예를 들어 { 1, 2, 3, 4, 5 }3 위치에 10을 넣고 싶을 경우, 3, 4, 5를 뒤로 한 칸씩 밀고 10을 삽입하여 { 1, 2, 10, 3, 4, 5 } 로 만든다
    • 용량이 부족하여 새로운 공간을 할당받을 경우, 해당 공간에 모든 요소를 복사해 넣어야 한다
    • 따라서 최악의 경우 O(n) 만큼의 시간복잡도가 소요된다

erase

iterator erase (iterator position);
iterator erase (iterator first, iterator last);
  • 벡터의 특정 위치에서 요소를 1개 이상 삭제한다
    • 첫 번째 오버로드는 position 위치의 단 한 개 요소를 삭제한다
    • 두 번째 오버로드는 first 반복자의 위치부터 last 반복자의 위치까지 다수의 요소를 삭제한다
  • 지워진 요소의 개수만큼 벡터의 크기 (size) 가 줄어든다

 

{ 1, 2, 3, 4, 5 }

// 3 을 삭제하고 싶은 경우
// 3 의 소멸자를 호출한 뒤, 뒤의 원소를 한 칸씩 당긴다
// 반환값은 (3 의 위치로 당겨진) 4 를 가리키는 반복자이다
{ 1, 2, 4, 5 }

// 2, 4 를 삭제하고 싶은 경우
// 2 부터 4 까지의 소멸자를 호출한 뒤, 뒤의 원소를 두 칸씩 당긴다
// 반환값은 (삭제된 요소 중 가장 앞에 있던 2 의 위치로 당겨진) 5 를 가리키는 반복자이다
{ 1, 5 }
  • 벡터의 중간에 위치한 요소를 삭제하기 위해 소멸자를 호출하고, 뒤의 요소를 (삭제한 요소의 개수만큼) 앞으로 당긴다
    • 두 오버로드 모두 맨 앞에 당겨진 요소의 위치를 가리키는 반복자를 반환한다
    • 앞으로 당겨진 요소가 3개인 경우, 3개의 요소 중 가장 첫 번째의 요소를 가리키는 반복자를 반환한다는 뜻이다

swap

void swap (vector& instance);
  • instance 벡터에 있는 값과 현재 벡터에 있는 값을 완전히 맞바꾼다
    • 그렇다는 것은, 현재 벡터 (this) 의 내용물이 instance 벡터에 있던 값들로 바뀌고, instance 벡터의 내용물이 현재 벡터 안에 있던 값들로 바뀐다

clear

void clear ();
  • 벡터를 비운다
    • 비운다는 것은, 모든 요소들의 소멸자를 호출하고, size를 0으로 만든다는 것이다
    • 모든 요소를 pop_back 한 것과 마찬가지다
  • 메모리 재할당이나 용량 (capacity) 의 변화 등이 생기는 것을 보장하지 않는다
    • 재할당이 일어날 수도 있고 아닐 수도 있으며 억지로 재할당을 일으킬 수도 있긴 한가 보다 ?

멤버 함수 - 할당자 관련

get_allocator

allocator_type get_allocator () const;
  • 현재 벡터가 가지고 있는 할당자 (allocator) 를 복사하여 반환한다

비멤버 함수 - 오버로드

operator==

template <class T, class Alloc>
bool operator== (const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs);
  • 두 벡터 lhs, rhs가 같은지 비교한다
    • lhs: left hand side
    • rhs: right hand side
    • 두 벡터가 같을 경우 true, 다를 경우 false
  • 벡터 크기 (size) 가 다를 경우 다른 벡터로 간주하며, 그 외에는 내용물을 비교한다

operator!=

template <class T, class Alloc>
bool operator!= (const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs);
  • 두 벡터 lhs, rhs가 다른지 비교한다
    • 두 벡터가 다를 경우 true, 같을 경우 false
  • 벡터 크기 (size) 가 다를 경우 다른 벡터로 간주하며, 그 외에는 내용물을 비교한다
    • 사실상 == 연산자 오버로드를 거꾸로 뒤집은 것과 같다

operator<

template <class T, class Alloc>
bool operator< (const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs);
  • 두 벡터 lhs, rhs 중 오른쪽 벡터가 더 큰지 비교한다
    • 오른쪽 벡터 (rhs) 가 더 클 경우 true, 그 외에 false

operator<=

template <class T, class Alloc>
bool operator<= (const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs);
  • 두 벡터 lhs, rhs 중 오른쪽 벡터가 더 크거나 같은지 비교한다
    • 오른쪽 벡터 (rhs) 가 더 크거나 같을 경우 true, 그 외에 false

operator>

template <class T, class Alloc>
bool operator> (const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs);
  • 두 벡터 lhs, rhs 중 왼쪽 벡터가 더 큰지 비교한다
    • 왼쪽 벡터 (lhs) 가 더 클 경우 true, 그 외에 false

operator>=

template <class T, class Alloc>
bool operator>= (const vector<T, Alloc>& lhs, const vector<T, Alloc>& rhs);
  • 두 벡터 lhs, rhs 중 왼쪽 벡터가 더 크거나 같은지 비교한다
    • 왼쪽 벡터 (lhs) 가 더 크거나 같을 경우 true, 그 외에 false

비멤버 함수

swap

template <class T, class Alloc>
void swap (vector<T, Alloc>& x, vector<T, Alloc>& y);
  • 두 벡터의 내용물을 맞바꾼다
  • 사실상 멤버 함수에 있는 그것과 똑같은 동작을 하지만… 기존의 swap 함수에서 요소들의 소유자를 변경함으로써 성능이 개선된 비멤버 오버로드라고 한다

참고 자료

https://legacy.cplusplus.com/reference/vector/vector/

https://en.cppreference.com/w/cpp/container/vector

 

아 참고 하라고 ~~~

Comments