[STL 컨테이너] vector
카테고리: STL
#include <vector>
🔔 vector 컨테이너 소개
원소들이 순서(인덱스)를 가지며 선형으로 배열되어 있는
Sequence Container
- 동적 배열로 구현되어 있다.
- 힙 메모리를 쓰지만 개발자가 직접
delete
해주지 않아도 된다. 사용되지 않으면 알아서 메모리 해제함.
- 힙 메모리를 쓰지만 개발자가 직접
Sequence Container
이므로- index만으로 탐색할 원소에 바로 참조가 가능하다.
- \(O(1)\) 시간 소요
- 순서대로 접근이 가능하다.
- \(O(N)\) 시간 소요
- index만으로 탐색할 원소에 바로 참조가 가능하다.
- 원소 추가
push_back
으로 벡터의 오른쪽 끝에 추가insert
으로 원하는 곳 중간에 삽임 by 반복자
- C++ 표준인
vector.h
에 템플릿 클래스로 정의가 되어 있는데, 특별히bool
은 특수화가 되어 있다.bool
일때는 메모리를 줄이기 위해 한개의 비트만 사용하도록 설계되어 있음.- 원래 C++의 최소 자료형 크기는 8 비트
다른 컨테이너들과 비교
list
와 다르게 일반 정적 배열처럼 벡터 컨테이너 원소들도 메모리상에서 연속적으로 존재한다.정적 배열
과는 다르게 스스로 공간을 할당하고 크기를 확장하고 줄일 수 있다.- 그래서 좀 더 여유있게 할당받기 때문에 (capacity) 정적 배열보다는 좀 더 많은 메모리를 필요로 한다.
- 원소를 중간에 삽입하는 작업은
deque
,list
보다는 느리다.- 다만 끝에 삽입하는 것은
vector
가 훨씬 빠르고 효율적.
- 다만 끝에 삽입하는 것은
capacity & size
new
,delete
연산을 최대한 줄이기 위하여 원소 추가시 미리 할당 받은capacity
내에서 공간을 땡겨온다
capacity
: 실제로 할당 받은 메모리. 여유 공간이라고 보면 된다. 항상size
보다 크게 조정된다.size
: 할당 받은capacity
중에서 실제 원소로 사용되고 있는 크기. 즉 원소 개수.- 참고 : std::vector를 스택처럼 사용하기
🔔 함수
- 정보
capacity
: 벡터의 여유 공간 리턴reserve(n)
: capacity 를 n 으로 설정
size()
: 벡터의 원소 개수 리턴resize(n)
: 원소 개수를 n 으로 설정max_size()
: 담을 수 있는 원소의 최대 크기를 리턴
data()
: 벡터가 사용하는 힙 메모리 주소를 리턴empty()
: 빈 벡터인지에 대해 true, false 리턴
- 반복자
begin()
: 벡터의 첫번째 원소를 가리키는 반복자end()
: 벡터읨 마지막 원소의 다음을 가리키는 반복자. 즉 빈 곳을 가리키며 벡터의 끝을 나타낸다.rbegin()
: 역순. 즉, 벡터의 마지막 원소를 가리키는 반복자rend()
: 역순. 즉, 벡터의 첫번째 원소의 바로 이전을 가리키는 반복자. 즉 빈 곳을 가리키며 벡터가 시작되는 곳을 나타낸다.
- 원소 접근
[n]
: 연산자 오버로딩이 되어있어[인덱스]
로 바로 해당 원소에 접근할 수 있다.==
<
같은 비교 연산자 오버로딩도 되어 있어서 두 벡터의 원소들이 전부 같은지, 전부 큰지 등등 비교할 수도 있다.=
연산자가 오버로딩 되어 있기 때문에 서로 다른 두 벡터끼리=
을 하면a 벡터 = b 벡터
하면 a 벡터에 b 벡터의 원소들이 전부 복사된다. a 벡터가 b 벡터와 동일해짐.
at(n)
: 해당 원소에 접근.[]
와 기능은 동일하나[]
보다 느리다.front()
: 첫번째 원소에 접근한다.back()
: 마지막 원소에 접근한다.
- 원소 추가
assign
assign(반복자, 반복자)
- 호출한 벡터의 해당 반복자 구간으로 할당한다.
assign(n, x)
- x 를 n 번만큼 반복하여 집어 넣는다.
push_back(원소)
: 원소를 벡터의 끝에 추가한다.emplace_back(가변인자)
push_back
과 같이 원소를 벡터의 끝에 추가한다는 것은 같으나 벡터에 객체를 추가할 때 밖에서 생성한 후 인수로 넘겨주어야 하는push_back
과 다르게 가변 인자로 객체 생성에 필요한 인자만 받은 후emplace_back
함수 내부에서 객체를 생성하여 벡터에 추가한다.push_back
보다 성능이 좋다.
insert(반복자, 원소)
: 해당 반복자가 가리키는 곳에 원소를 삽입insert(반복자, n, x)
: 해당 반복자가 가리키는 곳에 x 원소를 n 개 만큼 반복하여 삽입한다. 즉 n 개 삽입.
- 원소 삭제
pop_back(원소)
: 마지막 원소를 제거한다.vec.erase(vec.end() - 1)
와 같다.erase(반복자)
: 해당 반복자가 가리키는 곳의 원소를 삭제clear()
: 벡터의 원소 전부 삭제
- 원소 바꿔치기
swap(다른 벡터)
: 다른 벡터와 원소를 바꿔치기 한다.
- 할당자
get_allocator
: 할당자를 얻는다.
벡터 초기화 주의 사항
아직 아무런 공간이 없는 벡터일 때 👉
push_back
을 통해 삽입
내용물은 아직 없지만 공간은 잡혀있는 벡터일 때 👉
[]
연산자를 통해 삽입
vector<char> vec = {'a', 'b', 'c', 'd'};
vector<char> perm(r);
vector<pair<char, bool>> check(vec.size());
for(int i = 0; i < vec.size(); i++)
check.push_back(make_pair(vec[i], false)); // ❌런타임 에러 발생!
위와 같이 하면 에러가 발생하거나 공백들이 출력되는 등 정상적으로 출력되지 않는다. 왜 그럴까?
- check는 vec.size() 사이즈 만큼의 공간을 이미 갖고 있는 상태다.
vector<pair<char, bool>> check(vec.size());
라고 선언해서! - 그런 상태에서
push_back
을 해버리면 의미있는 내용물은 아직 없지만 vec.size() 사이즈만큼의 공간을 이미 차지하는 상태에서 뒤에 원소를 추가해주려고 하니 에러가 발생하는 것이다. 특히나vecotr<int>
타입인 경우엔 자동으로 미리 잡아둔 해당 공간들을 0 으로 초기화 해주기 때문에 문제가 없을지 몰라도vector<pair<char, bool>>
이렇게 pair나 혹은 사용자 정의 객체 타입을 원소로 사용하는 벡터일 경우엔 자동으로 어떤 값으로 초기화 할지 정보가 없기 때문에 초기화 되지 않아서 더더욱 문제가 생긴다.
vector<pair<char, bool>> check;
for(int i = 0; i < vec.size(); i++)
check.push_back(make_pair(vec[i], false));
vector<pair<char, bool>> check;
그냥 이렇게 사이즈 0 인 아무것도 없는 빈 공간의 컨테이너로 선언한 후 그 이후에push_back
으로 뒤에 추가해주면 문제가 발생하지 않는다.
vector<int> vec;
vec[0] = 2; // ❌런타임 에러 발생!
벡터 vec
은 아직 아무런 공간을 차지 하지 않는 벡터다. 그런 상황에서 vec[0]
을 통해 없는 공간을 사용하려고 하면 위와같이 에러가 발생한다.
vector<int> vec(3);
vec[0] = 2;
위와 같이 vec
을 선언시 int 데이터가 3 개 들어갈 만큼 공간을 미리 확보해두면 vec[0]
을 통해 접근해도 문제가 없다. 이미 vec
로서 존재하는 공간에 접근하려고 하는 것이기 때문이다! 그리고 저렇게 미리 공간을 잡아두면 vec[0]~vec[2]는 0
으로 초기화를 해준다. (int 벡터의 경우)
🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄
댓글남기기