Vector란 C++ 표준라이브러리(STL)에 있는 컨테이너(Container)이다.
Vector를 생성하면 메모리 heap에 배열이 동적으로 할당된다.
스택과 같은 느낌이라고 생각하면 된다.
(삽입과 삭제가 여러번 반복된다면 vector보다는 list, deque 자료구조를 사용하는 것을 추천)
Vector 사용법
1. Vector 헤더를 include.
2. Vector 선언.
- vector<datatype> 변수이름
- ex) vector<int>numbers;
Vector 생성 방법
- vector<int> v; ▶ 빈 벡터 생성
- vector<int> v(4); ▶ 0으로 초기화 되어 있는 4 크기의 벡터 생성
- vector<int> v(4, 2); ▶ 2로 초기화 되어 있는 4 크기의 벡터 생성
- vector<int> v = {1, 2, 3}; ▶ int형 벡터 생성하고, 원소를 1, 2, 3으로 초기화
- vector<int> v2(v1); ▶ v1을 복사한 v2 벡터 생성
- vector<int> v = {{1, 2}, {3, 4}}; ▶ int형 벡터 배열 생성 (행-가변, 열-불변)
- vector<vector<int>> v; ▶ int형 2차원 벡터 생성 (행-가변, 열-가변)
Vector 멤버 함수
초기화
- v.assign(4, 2); ▶ 원소가 2의 값으로 초기화된 4개의 원소가 담긴 벡터 생성
접근
- v.at(i); ▶ 벡터의 i번째 원소를 참조. v[i]보다는 느리지만 범위를 검사하므로 안전. (범위 넘어갈 시 예외처리)
- v[i]; ▶ 벡터의 i번째 원소를 참조. 범위 검사를 하지 않아 v.at(i)보다는 빠름 (보통은 효율성을 위해 이것을 권장)
- v.front(); ▶ 벡터의 첫 번째 원소를 참조
- v.back(); ▶ 벡터의 마지막 원소를 참조
Iterator
- v.begin(); ▶ 벡터의 시작 주소값 반환
- v.end(); ▶ (마지막 원소 + 1)의 주소값 반환
- v.rbegin(); ▶ reverse begine으로, 벡터의 마지막 지점을 시작점으로서 반환
- v.rend(); ▶ reverse end로, 벡터의 (시작+1) 지점을 끝부분으로서 반환
원소 삽입 및 제거
- v.push_back(k); ▶ 벡터의 마지막 원소 뒤에 k를 삽입. 이 함수는 값을 넣는 과정에 복사생성자를 호출하여 모든 값들을 새로운 메모리에 복사한 후에 해당 위치에 값을 넣음. 따라서 오버헤드가 크게 발생하여 비효율적.
- v.pop_back(); ▶ 벡터의 마지막 원소를 제거
- v.insert(삽입 위치, 값); ▶ ex) v.insert(1, 2); 1번째 위치에 원소 2 삽입
- v.insert(삽입 위치, 개수, 값); ▶ ex) v.insert(1, 2, 3); 1번째 위치에 2개의 3으로 초기화된 원소를 삽입
- v.emplace(삽입 위치, 값); ▶ insert와 같은 기능으로 삽입위치에 값을 삽입. 다만 구조가 다름. 원소를 내부에서 생성하는 방식으로 컨테이너에 추가되기 때문에 임시 객체를 아예 생기지 않게 하거나, 그 횟수를 줄일 수 있음
- v.emplace_back(k); ▶ 벡터의 마지막 부분에 원소 k 삽입. 복사생성자를 호출하지 않기 때문에 push_back보다 이것을 사용하는 것을 권장
- v.erase(삭제위치); ▶ 해당 삭제위치의 원소를 삭제. 다만 원소가 제거되는 것(Size 감소)이고 할당된 메모리(Capacity)는 그대로 유지된다.
- v.erase(start, end); ▶ start 이상, end 미만의 원소들을 삭제한다.
- v.clear(); ▶ 모든 원소를 제거하지만 메모리는 남긴다. 따라서 clear한 벡터를 더는 사용하지 않는 경우에는, 아무것도 들어 있지 않은 capacity=0인 벡터와 swap하는 형태로 메모리도 모두 없애는 것을 권장.
- v2.swap(v1); ▶ v1과 v2의 원소와 capacity를 스왑한다.
기타
- v.reverse(n); ▶ n개의 원소를 저장할 위치를 예약(동적할당). 만약 push_back에 의해서 capacity를 초과하는 원소를 삽입하는 경우에는 벡터를 복사하여 새로이 메모리를 할당하고 기존 벡터를 삭제하는 식으로 동작되는데, 이것을 사용하면 불필요한 벡터의 생성과정을 피할 수 있음.
- v.resize(n); ▶ 벡터의 크기를 n으로 변경. 만약 기존 벡터보다 사이즈가 커진 경우엔 추가된 원소들을 0으로 초기화
- v.resize(n, k); ▶ 벡터의 크기를 n으로 변경하고, 추가되는 원소들은 k로 초기화
- v.size(); ▶ 벡터에 들어 있는 원소의 개수를 반환
- v.capacity(); ▶ 벡터가 할당된 크기를 반환 (Size랑 다름). Size는 할당된 메모리에 존재하는 원소의 개수, Capacity는 할당된 메모리의 크기
- v.empty(); ▶ 벡터가 비어 있다면(Size=0, 원소가 없다면) 반환값이 True, 그렇지 않다면 False
- v.shrink_to_fit(); ▶ Capacity를 원소의 개수에 맞춰서 메모리를 절약
Vector 응용
배열 뒤집기
- 1. Reverse 이용 ▶ algorithm 헤더를 불러와야 함
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main() {
vector<int> num_list = {1, 2, 3, 4, 5};
reverse(begin(num_list), end(num_list));
for (int i=0; i<num_list.size(); i++){
cout << num_list[i] << " ";
}
return 0;
}
5 4 3 2 1
- 2. Vector 이용
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<int> num_list = {1, 2, 3, 4, 5};
vector<int> answer;
answer = vector(num_list.rbegin(), num_list.rend());
for (int i=0; i<answer.size(); i++){
cout << answer[i] << " ";
}
return 0;
}
5 4 3 2 1