[STL] vector 벡터 정리 및 예제
[STL] vector 벡터 정리 및 예제
vector 컨테이너는 대표적인 시퀀스 컨테이너로 배열과 비슷하여 사용이 쉬우며 자주 사용된다.
vector는 임의 접근 반복자(Random Access Iterator)를 지원하는 배열 기반 컨테이너이다.
vector의 가장 큰 특징 중 하나는 원소가 하나의 메모리 블록에 연속하게 저장된다는 것이다.
그렇다 보니 원소가 추가되거나 삽입될 때 메모리 재할당이 발생할 수 있고 상당한 비용을 지불하게 된다.
그래서 메모리 할당 크기를 알 수 있게 capacity() 함수를 제공하며 한번에 메모리를 할당할 수 있는 reserve() 함수도 제공된다.
원소가 연속하게 저장되므로 [] 연산자 또는 at 으로 읽기에는 빠르지만 insert(), erase(), push_back() 등은 비효율적으로 동작한다.
템플릿 형식 | |
template<typename T, typename Allocator = allocator<T>> class vector | T는 vector 컨테이너 원소의 형식 |
생성자 | |
vector v | v는 빈 컨테이너이다. |
vector v(n) | v는 기본값으로 초기화된 n개의 원소를 갖는다. |
vector v(n,x) | v는 x 값으로 초기화된 n개의 원소를 갖는다. |
vector v(v2) | v는 v2 컨테이너의 복사본이다.(복사 생성자 호출) |
vector v(b,e) | v는 반복자 구간 [b,e)로 초기화된 원소를 갖는다. |
멤버함수 | |
v.assign(n,x) | v에 x 값으로 n개의 원소를 할당한다. |
v.assign(b,e) | v를 반복자 구간 [b,e)로 할당한다. |
v.at(i) | v의 i번째 원소를 참조한다. |
v.back() | v의 마지막 원소를 참조한다. |
p=v.begin() | p는 v의 첫 원소를 가리키는 반복자 |
x=v.capacity() | x는 v에 할당된 공간의 크기 |
v.clear() | v의 모든 원소를 제거한다. |
v.empty() | v가 비었는지 조사한다. |
p=v.end() | p는 v의 끝을 표식하는 반복자 |
p=v.erase(p) | p가 가리키는 원소를 제거한다. q는 다음 원소를 가리킨다. |
q=v.erase(b,e) | 반복자 구간 [b,e)의 모든 원소를 제거한다. q는 다음 원소 |
v.front() | v의 첫 번째 원소를 참조한다. |
q=v.insert(p,x) | p가 가리키는 위치에 x 값을 삽입한다. q는 삽입한 원소를 가리키는 반복자다. |
v.insert(p,n,x) | p가 가리키는 위치에 n개의 x 값을 삽입한다. |
v.insert(p,b,e) | p가 가리키는 위치에 반복자 구간 [b,e)의 원소를 삽입한다. |
x=v.max_size() | x는 v가 담을 수 있는 최대 원소의 개수(메모리의 크기) |
v.pop_back() | v의 마지막 원소를 제거한다. |
v.push_back() | v의 끝에 x를 추가한다. |
p=v.rbegin() | p는 v의 역 순차열의 첫 원소를 가리키는 반복자다. |
p=v.rend() | p는 v의 역 순차열의 끝을 표식하는 반복자 |
v.reserve(n) | n개의 원소를 저장할 공간을 예약한다. |
v.resize(n) | v의 크기를 n으로 변경하고 확장되는 공간의 값을 기본값으로 초기화 한다. |
v.resize(n,x) | v의 크기를 n으로 변경하고 확장되는 공간의 값을 x 값으로 초기화한다. |
v.size() | v의 원소 갯수 |
v.swap(v2) | v와 v2를 swap한다. |
연산자 | |
v1==v2 | v1과 v2의 모든 원소가 같은가? (bool) |
v1!=v2 | v1과 v2의 모든 원소 중 하나라도 다른 원소가 있는가? |
v1<v2 | 문자열 비교처럼 v2가 v1보다 큰가? |
v1>v2 | 문자열 비교처럼 v1이 v2보다 큰가? |
v[i] | v의 i번째 원소를 참조한다. |
멤버 형식 | |
allocator_type | 메모리 관리자 형식 |
const_iterator | const 반복자 형식 |
const_pointer | const value_type* 형식 |
const_reference | const value_type& 형식 |
const_reverse_iterator | const 역 반복자 형식 |
difference_type | 두 반복자 차이의 형식 |
iterator | 반복자 형식 |
pointer | value_type* 형식 |
reference | value_type& 형식 |
reverse_iterator | 역 반복자 형식 |
size_type | 첨자(index)나 원소의 개수 등의 형식 |
value_type | 원소의 형식 |
시퀀스 컨테이너는 차례차례 원소를 추가하고 제거하는 push_back()과 pop_back()을 가지며, 첫 원소와 마짐가 원소를 참조하는 front()와 back()을 가진다. 또한, 지정한 위치에 원소를 삽입할 수 있는 insert()를 가진다.
vector는 앞쪽이 막혀 있는 형태로 앞쪽에는 원소를 추가/제거할 수 없으며 뒤쪽에만 추가/제거할 수 있다.
* vector 사용 예제 1
#include <iostream> #include <vector> using namespace std; int main(){ vector<int> v; v.reserve(8); // 벡터 메모리 공간 8 예약 할당 v.push_back(10); v.push_back(20); v.push_back(30); v.push_back(40); v.push_back(50); for (vector<int>::size_type i = 0; i < v.size(); ++i) cout << v[i] << endl; cout << endl; cout << "size : " << v.size() // 벡터 원소 개수 << " capacity : " << v.capacity() // 벡터의 할당된 메모리의 크기 << " max_size : " << v.max_size() << endl; // 최대 저장 가능한 원소 개수 cout << endl << "-- resize(10) -- " << endl; v.resize(10); // 벡터의 원소 갯수를 10개로 확장, 추가된 공간은 디폴트 0으로 채워진다. for (vector<int>::size_type i = 0; i < v.size(); ++i) // 벡터의 size 타입으로 i를 지정한다 (unsigned int) cout << v[i] << endl; cout << endl; cout << "size : " << v.size() << " capacity : " << v.capacity() << " max_size : " << v.max_size() << endl; cout << endl << "-- resize(3) -- " << endl; v.resize(3); // 벡터의 원소 갯수를 3개로 축소, capacity는 변화 없다. for (vector<int>::size_type i = 0; i < v.size(); ++i) cout << v[i] << endl; cout << endl; cout << "size : " << v.size() << " capacity : " << v.capacity() << " max_size : " << v.max_size() << endl; cout << endl << "-- vector clear() -- " << endl; v.clear(); // 벡터 비운다 capacity(메모리) 는 그대로 남아있다. if (v.empty()){ // 벡터에 원소가 없는지 확인한다. cout << "벡터에 원소가 없다." << endl; } cout << "size : " << v.size() << " capacity : " << v.capacity() << " max_size : " << v.max_size() << endl; return 0; } |
결과 : 10 20 30 40 50 size : 5 capacity : 8 max_size : 1073741823 -- resize<10> -- 10 20 30 40 50 0 0 0 0 0 size : 10 capacity : 12 max_size : 1073741823 -- resize<3> -- 10 20 30 size : 3 capacity : 12 max_size : 1073741823 벡터에 원소가 없다. size : 0 capacity : 12 max_size : 1073741823 |
- v.reserve(8) : 벡터의 메모리 공간(capacity) 을 미리 할당한다. * 추가할당이 아님
- vector<int>::size_type : 벡터의 size 의 반환 타입을 가져온다 (unsigned int)
- v.resize(10) : 벡터의 원소 갯수를 수정한다. (size 를 줄여도 capacity는 그대로다)
- v.clear() : 벡터를 비운다 (capacity 크기는 그대로다)
- v.empty() : 벡터가 비워져 있는지 확인한다.
* for문으로 vector를 탐색할 때, v.size() 만큼 i를 돌리려면, v.size()의 타입과 i 가 같아야 한다.
* v.capacity()는 벡터에 할당된 메모리 공간이다.
새로운 원소가 벡터에 추가되면 메모리 공간이 추가적으로 할당된다.
매번 새로운 원소가 들어올 때마다 새로운 메모리가 할당되는 것은 비효율적이다.
capacity가 모자랄 경우 capacity/2 만큼의 capacity를 늘려간다.
만약 입력될 원소의 갯수를 알 수 있다면 reserve 를 사용하여 미리 capapcity 메모리를 할당해 놓으면 효율적이다.
* v.clear()를 사용하면 벡터의 원소를 비운다.
하지만 capacity는 그대로 남아 있다. 비어있는 벡터인데 메모리를 할당하고 있는 것은 아깝다.
이럴경우 clear()를 사용하기 보다 . 임시 벡터와 swap 을 통해 교환하면 메모리까지 해제할 수 있다.
#include <iostream> #include <vector> using namespace std; int main(){ vector<int> v(5); // 0으로 초기화된 5개의 원소 cout << "size : " << v.size() << " capacity : " << v.capacity() << endl; vector<int>().swap(v); // 임의 벡터와 교환한다. cout << "size : " << v.size() << " capacity : " << v.capacity() << endl; vector<int> v1; v1.push_back(10); v1.push_back(20); v1.push_back(30); v1.push_back(40); v1.push_back(50); cout << v1[0] << ", " << v1.at(0) << ", " << v1.front() << endl; // 첫번째 원소 cout << v1[4] << ", " << v1.at(4) << ", " << v1.back() << endl; // 마지막 원소 v1.front() = 100; v1.back() = 500; cout << v1[0] << ", " << v1.at(0) << ", "<< v1.front() << endl; // 첫번째 원소 cout << v1[4] << ", " << v1.at(4) << ", " << v1.back() << endl; // 마지막 원소 try{ cout << v.at(10) << endl; // 범위를 벋어난 호출 throw out_of_range 예외 } catch (out_of_range &e){ cout << e.what() << endl; } return 0; } |
결과 : size : 5 capacity : 5 size : 0 capacity : 0 10, 10, 10 50, 50, 50 100, 100, 100 500, 500, 500 invalid vector<T> subscript |
* vector<int>().swap(v); : 임의 벡터와 swap을 하면서 벡터를 비우고 할당된 메모리(capacity)까지 해제한다.
* v.front()는 벡터의 첫번째 요소를 반환하고 v.back()는 마지막 요소를 반환한다.
* 벡터의 임의 요소에 접근하는 방법으로는 [] 연산자와 at 멤버함수가 있다.
[] 연산자를 사용하면 접근이 빠르지만 범위 점검을 하지 않는다.
at() 멤버 함수를 사용하여 접근하면 범위 점검을 수행하며, 범위에 벗어난 요소에 접근하면 out_of_range 예외를 throw 하여 예외를 처리할 수 있다.
출처: https://hyeonstorage.tistory.com/324?category=614599 [개발이 하고 싶어요]
'기타 > C++ STL' 카테고리의 다른 글
[STL] multiset 정리 및 예제 (0) | 2019.07.30 |
---|---|
[STL] set 정리 및 예제 (0) | 2019.07.30 |
[STL] list 정리 및 예제 (0) | 2019.07.30 |
[STL] deque 정리 및 예제 (0) | 2019.07.30 |
[STL] not2 함수 (0) | 2019.07.30 |
[STL] 역방향 반복자 (reverse_iterator) (1) | 2019.07.30 |
[STL] 스택(stack) 기본 예제 (0) | 2019.07.30 |
[STL] sort() 정렬 예제 (0) | 2019.07.30 |