Rylah's Study & Daily Life
STL 06. 시퀀스 컨테이너 (Vector) 본문
Vector 컨테이너는 대표적인 시퀀스 컨테이너로 배열과 비슷하여 사용이 쉬우므로 자주 사용한다.
Vector의 주요 인터페이스와 특징
템플릿 형식 | |
template<typename T, typename Allocator = allocator<T>> class vector |
T는 vector 컨테이너 원소의 형식 |
<Vector의 템플릿 형식>
생성자 | |
vector v | v는 빈 컨테이너 |
vector v(n) | v는 기본값(0)으로 초기화된 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번째 원소를 참조한다. (const, 비 const 버전이 존재하며 범위 점검을 포함한다.) |
v.back() | v의 마지막 원소를 참조한다. (const, 비 const 버전이 있음) |
p = v.begin() | p는 v의 첫번째 원소를 가리키는 반복자(const, 비 const 버전이 있음) |
x = v.capacity() | x는 v에 할당된 공간의 크기 |
v.clear() | v의 모든 원소를 제거한다. |
v.empty() | v가 비었는지 조사한다. |
p=v.end() | p는 v의 끝을 표시하는 반복자다(const, 비 const 버전이 있음) |
q=v.erase(p) | p가 가리키는 원소를 제거한다. q는 다음 원소를 가리킨다. |
q=v.erase(p,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(x) | v의 끝에 x를 추가한다. |
p = v.rbegin() | p는 v의 역 순차열의 첫 원소로 가리키는 반복자다. (const, 비 const 버전이 있음) |
p = v.rend() | p는 v의 역 순차열의 끝을 표시하는 반복자(const, 비 const 버전이 있음) |
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의 모든 원소 중 하나라도 다른 원소가 있는가? (bool) |
v1 < v2 | 문자열 비교처럼 v2가 v1보다 큰가? (bool) |
v1 <= v2 | 문자열 비교처럼 v2가 v1보다 크거나 같은가? (bool) |
v1 > v2 | 문자열 비교처럼 v1이 v2보다 큰가? (bool) |
v1 >= v2 | 문자열 비교처럼 v1이 v2보다 크거나 같은가? (bool) |
v[i] | v의 i번째 원소를 참조한다.(const, 비 const 버전이 있으며 범위 점검이 없음) |
<vector의 인터페이스>
멤버 형식 | |
allocator_type | 메모리 관리자 형식 |
const_iterator | cosnt 반복자 형식 |
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 | 원소의 형식 |
<vector의 템플릿 멤버 형식>
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
int main(void) {
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(40);
v.push_back(60);
v.push_back(120);
for (int i = 0; i < v.size(); i++) {
cout << v[i] << endl;
}
cout << typeid(vector<int>::size_type).name() << endl;
for (vector<int>::size_type i = 0; i < v.size(); ++i)
cout << v[i] << " ";
cout << endl << endl;
cout << "v.size() : " << v.size() << endl;
cout << "v.capacity() : " << v.capacity() << endl;
cout << "v.max_size() : " << v.max_size() << endl;
cout << endl << endl;
vector<int> v2;
cout << "vector's capacity() " << endl;
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(10);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(20);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(40);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(80);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(120);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(240);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(480);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(960);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(1920);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
v2.push_back(3840);
cout << "size : " << v2.size() << " capacity() : " << v2.capacity() << endl;
return 0;
}
Dev C++과 Visual Studio 컴파일러 차이로 출력값에서 차이가 많이 난다.
- 차이점
1. typeid에서 값을 받아오는게 unsigned int vs y가 된다.
2. max_size에 최대 사이즈 수가 다르다.
3. capacity의 증가 폭이 다르다.
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
int main(void) {
vector<int> v3;
v3.reserve(8);
cout << "vector's capacity() " << endl;
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(10);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(20);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(40);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(80);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(120);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(240);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(480);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(960);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(1920);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
v3.push_back(3840);
cout << "size : " << v3.size() << " capacity() : " << v3.capacity() << endl;
for (vector<int>::size_type i = 0; i < v3.size(); ++i) {
cout << v3[i] << " ";
}
cout << endl;
return 0;
}
<위 : Dev C++, 아래 : Visual Studio 2019>
8까지의 메모리 크기(capacity)를 reserve 함수로 미리 할당해준 것이다.
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
int main(void) {
vector<int> v4(5); // 0으로 초기화된 size가 5인 vector 컨테이너
v4.push_back(10);
v4.push_back(20);
v4.push_back(40);
v4.push_back(80);
v4.push_back(160);
for (vector<int>::size_type i = 0; i < v4.size(); ++i) {
cout << v4[i] << " ";
}
cout << endl;
vector<int> v5(5); // 0으로 초기화된 size가 5인 vector 컨테이너
v5[0] = 10; // 0 -> 10
v5[1] = 20; // 0 -> 20
v5[2] = 40; // 0 -> 40
v5[3] = 80; // 0 -> 80
v5[4] = 160;// 0 -> 160
for (vector<int>::size_type i = 0; i < v5.size(); ++i)
cout << v5[i] << " ";
cout << endl;
return 0;
}
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
int main(void) {
vector<int> v6(5); // 기본값 0 으로 초기화된 size가 5인 컨테이터 vector
for (vector<int>::size_type i = 0; i < v6.size(); ++i) {
cout << v6[i] << " ";
}
cout << endl;
vector<int> v7(5, 0); // 기본값 0으로 초기화된 size가 5인 컨테이너 vector
for (vector<int>::size_type i = 0; i < v7.size(); ++i) {
cout << v7[i] << " ";
}
cout << endl;
vector<int> v8(5, 10); // 기본값 10으로 초기화 된 size가 5인 컨테이너 vector
for (vector<int>::size_type i = 0; i < v8.size(); ++i) {
cout << v8[i] << " ";
}
cout << endl;
return 0;
}
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
int main(void) {
vector<int> v9(5); // 기본값이 0으로 초기화된 size가 5인 컨테이너 vector
v9[0] = 10;
v9[1] = 50;
v9[2] = 105;
v9[3] = 185;
v9[4] = 204;
for (vector<int>::size_type i = 0; i < v9.size(); ++i) {
cout << v9[i] << " ";
}
cout << endl;
cout << "Size : " << v9.size() << " Capacity : " << v9.capacity() << endl;
v9.resize(10); // 기본값이 0으로 초기화된 size가 10인 컨테이너로 변경
for (vector<int>::size_type i = 0; i < v9.size(); ++i) {
cout << v9[i] << " ";
}
cout << endl;
cout << "Size : " << v9.size() << " Capacity : " << v9.capacity() << endl;
v9.resize(5); // 기본값이 0으로 초기화된 size가 5인 컨테이너로 변경 capacity는 변하지 않음
for (vector<int>::size_type i = 0; i < v9.size(); ++i) {
cout << v9[i] << " ";
}
cout << endl;
cout << "Size : " << v9.size() << " Capacity : " << v9.capacity() << endl;
return 0;
}
#include <iostream>
#include <vector>
#include <typeinfo>
using namespace std;
int main(void) {
vector<int> v10(5);
v10[0] = 104;
v10[1] = 503;
v10[2] = 10566;
v10[3] = 1851;
v10[4] = 2044;
for (vector<int>::size_type i = 0; i < v10.size(); ++i)
cout << v10[i] << " ";
cout << endl;
cout << "Size : " << v10.size() << " Capacity : " << v10.capacity() << endl;
v10.clear(); // v10을 비운다.
cout << "after V.Clear() " << endl << "Size : " << v10.size() << " Capacity : " << v10.capacity() << endl;
if (v10.empty()) // 비었다면 ? 실행된다.
cout << "v10에 원소가 없어요 " << endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main(void) {
vector<int> v(5);
cout << "Size : " << v.size() << " Capacity : " << v.capacity() << endl;
vector<int>().swap(v);
// 기본 생성자로 만든 vector 컨테이너와 v 컨테이너를 Swap
cout << "Size : " << v.size() << " Capacity : " << v.capacity() << endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main(void) {
vector<int> v(5);
cout << "Size : " << v.size() << " Capacity : " << v.capacity() << endl;
vector<int>().swap(v);
// 기본 생성자로 만든 vector 컨테이너와 v 컨테이너를 Swap
cout << "Size : " << v.size() << " Capacity : " << v.capacity() << endl;
cout << endl;
vector<int> v1;
v1.push_back(3002);
v1.push_back(40921);
v1.push_back(33940);
vector<int> v2;
v2.push_back(2912);
v2.push_back(4921);
v2.push_back(33940);
for (vector<int>::size_type i = 0; i < v1.size(); ++i) {
cout << v1[i] << ", " << v2[i] << endl;
}
cout << endl;
v1.swap(v2); // v1과 v2를 Swap
for (vector<int>::size_type i = 0; i < v1.size(); ++i) {
cout << v1[i] << ", " << v2[i] << endl;
}
cout << endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main(void) {
vector<int> v;
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] << " ";
}
cout << endl;
cout << v[0] << ", " << v.front() << endl; // 첫번째 원소
cout << v[4] << ", " << v.back() << endl; // 마지막 원소
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main(void) {
vector<int> v;
v.push_back(10);
v.push_back(40);
v.push_back(70);
v.push_back(120);
v.push_back(150);
for (vector<int>::size_type i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl;
cout << v[0] << ", " << v.front() << endl; // 첫번째 원소
cout << v[4] << ", " << v.back() << endl; // 마지막 원소
cout << endl;
v.front() = 32768; // 첫번째 원소 수정
v.back() = 65536; // 마지막 원소 수정
for (vector<int>::size_type i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl << endl;
v[0] = 5030; // 범위 점검 없는 0 index 참조
v[4] = 2105; // 범위 점검 없는 4 index 참조
for (vector<int>::size_type i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl << endl;
v.at(0) = 249495; // 범위 점검 있는 0 index 원소의 참조
v.at(4) = 594942; // 범위 점검 있는 4 index 원소의 참조
for (vector<int>::size_type i = 0; i < v.size(); ++i) {
cout << v[i] << " ";
}
cout << endl << endl;
// [] 연산자와 at의 기능이나 결과는 동일
// 범위 점검의 여부가 차이임 at 함수는 in range이면 참조해서 반환하고 아니면 out of range 예외를 발생함.
try {
cout << v.at(0) << endl;
cout << v.at(3) << endl;
cout << v.at(6) << endl; // throw out_of_range 예외
}
catch (out_of_range& e) {
cout << e.what() << endl << endl;
}
vector<int> v1(5, 1); // 초기값 1의 5개의 원소를 가지는 컨테이너 vector 생성
for (vector<int>::size_type i = 0; i < v1.size(); ++i) {
cout << v1[i] << " ";
}
cout << endl;
v1.assign(5, 2); // 5개 원소 값을 2로 할당
for (vector<int>::size_type i = 0; i < v1.size(); ++i) {
cout << v1[i] << " ";
}
cout << endl << endl;
vector<int> v2;
v2.push_back(50);
v2.push_back(550);
v2.push_back(750);
v2.push_back(1250);
v2.push_back(2250);
for (vector<int>::size_type i = 0; i < v2.size(); ++i) {
cout << v2[i] << " ";
}
cout << endl;
for (vector<int>::iterator iter = v2.begin(); iter != v2.end(); ++iter)
cout << *iter << " ";
cout << endl << endl;
vector<int> v3;
v3.push_back(50);
v3.push_back(150);
v3.push_back(603);
v3.push_back(202);
v3.push_back(6035);
vector<int>::iterator iter = v3.begin(); // 시작 원소 50을 가리킨다.
cout << *iter << endl;
iter += 2; // 원소 603을 가리킨다.
cout << *iter << endl;
iter -= 1; // 원소 150을 가리킨다.
cout << *iter << endl;
cout << endl << endl;
vector<int> v4;
v4.push_back(3204);
v4.push_back(3201);
v4.push_back(3202);
v4.push_back(3203);
v4.push_back(3206);
vector<int>::iterator iter_a = v4.begin();
vector<int>::const_iterator c_iter_a = v4.begin();
cout << *iter_a << endl; // 가리키는 원소의 참조
cout << *c_iter_a << endl;
cout << *++iter_a << endl;
cout << *++c_iter_a << endl;
*iter_a = 100; // 일반 반복자는 가리키는 원소를 변경 할 수 있음
//*c_iter_a = 500; // const는 상수라서 변경이 불가능
cout << *iter_a << endl;
cout << endl << endl;
vector<int> v5;
int arrayF[5]{ 83000, 73000, 13000, 53000, 23000 };
v5.push_back(83204);
v5.push_back(73201);
v5.push_back(13202);
v5.push_back(53203);
v5.push_back(23206);
vector<int>::iterator iter5 = v5.begin(); // iter5는 다음 원소로 이동 가능하고 원소의 변경이 가능한 반복자이다.
int* p = arrayF;
cout << *iter << ", " << *p << endl; // iter5는 p처럼 동작한다.
vector<int>::const_iterator citer5 = v5.begin(); // citer5는 다음 원소로 이동이 가능하지만 원소의 변경이 불가능한 반복자이다.
const int* cp = arrayF;
cout << *citer5 << ", " << *cp << endl; //citer5는 cp처럼 동작한다.
const vector<int>::iterator iter5_const = v5.begin(); // iter5_const는 다음 원소로 이동이 불가능하고 원소의 변경은 가능한 반복자이다.
int* const p_const = arrayF; // iter5_const는 p_const처럼 동작한다.
cout << *iter5_const << ", " << *p_const << endl;
const vector<int>::const_iterator citer5_const = v5.begin(); // citer5_const는 다음 원소로 이동이 불가능하고 원소의 변경이 불가능한 반복자이다.
const int* const cp_const = arrayF; // citer5_const는 cp_const처럼 동작한다.
cout << *citer5_const << ", " << *cp_const << endl;
return 0;
}
#include <iostream>
#include <vector>
using namespace std;
int main(void) {
vector<int> v;
v.push_back(10);
v.push_back(20);
v.push_back(30);
v.push_back(40);
v.push_back(50);
vector<int>::iterator iter; // 정방향 반복자
vector<int>::reverse_iterator r_iter; //역방향 반복자
for (iter = v.begin(); iter != v.end(); ++iter)
cout << *iter << " ";
cout << endl;
for (r_iter = v.rbegin(); r_iter != v.rend(); ++r_iter)
cout << *r_iter << " ";
cout << endl << endl;
vector<int> v1;
v1.push_back(10);
v1.push_back(20);
v1.push_back(30);
v1.push_back(40);
v1.push_back(50);
vector<int>::iterator iter1 = v1.begin() + 2;
vector<int>::iterator iter2;
// iter1가 가리키는 위치에 정수 100을 삽입
// iter2는 삽입한 정수를 가리키는 반복자
iter2 = v1.insert(iter1, 100);
for (iter1 = v1.begin(); iter1 != v1.end(); ++iter1)
cout << *iter1 << " ";
cout << endl;
cout << *iter2 << endl;
cout << endl;
vector<int> v2;
v2.push_back(10);
v2.push_back(20);
v2.push_back(30);
v2.push_back(40);
v2.push_back(50);
vector<int>::iterator iter3 = v2.begin() + 2;
//iter가 가리키는 위치에 정수 100을 3개 삽입1
v2.insert(iter3, 3, 100);
for (iter3 = v2.begin(); iter3 != v2.end(); ++iter3) {
cout << *iter3 << " ";
}
cout << endl;
vector<int> v3;
v3.push_back(100);
v3.push_back(200);
v3.push_back(300);
iter3 = v3.begin() + 1;
// iter3가 가리키는 위치에 [v3.begin(), v3.end()) 구간의 원소 삽입
v3.insert(iter3, v2.begin(), v2.end());
for (iter3 = v3.begin(); iter3 != v3.end(); ++iter3)
cout << *iter3 << " ";
cout << endl << endl;
vector<int> v4;
v4.push_back(10);
v4.push_back(20);
v4.push_back(30);
v4.push_back(40);
v4.push_back(50);
v4.push_back(60);
vector<int>::iterator iter4;
vector<int>::iterator iter5;
for (iter4 = v4.begin(); iter4 != v4.end(); ++iter4)
cout << *iter4 << " ";
cout << endl;
iter4 = v4.begin() + 2;
// iter가 가리키는 위치의 원소를 제거하기 위함이다. iter4의 다음 원소는 40이고 원소 30을 제거한다.
iter5 = v4.erase(iter4);
for (iter4 = v4.begin(); iter4 != v4.end(); ++iter4)
cout << *iter4 << " ";
cout << endl;
// [v4.begin() + 1, v4.end() ) 구간 원소 제거
iter5 = v4.erase(v4.begin() + 1, v4.end());
for (iter4 = v4.begin(); iter4 != v4.end(); ++iter4)
cout << *iter4 << " ";
cout << endl << endl;
vector<int> v5;
v5.push_back(50);
v5.push_back(150);
v5.push_back(250);
v5.push_back(350);
v5.push_back(450);
vector<int> v6(v5.begin(), v5.end()); // 순차열 v5.begin(), v5.end()로 v6 초기화 생성자로 초기화 하는 방법
vector<int>::iterator iter6;
for (iter6 = v6.begin(); iter6 != v6.end(); ++iter6)
cout << *iter6 << " ";
cout << endl;
vector<int> v7;
v7.assign(v5.begin(), v5.end());
// v7에 순차열 [v5.begin(), v5.end()) 할당 , assign으로 초기화 하는 방법
for (iter6 = v7.begin(); iter6 != v7.end(); ++iter6)
cout << *iter6 << " ";
cout << endl;
vector<int> v8;
v8.push_back(10);
v8.push_back(120);
v8.push_back(140);
v8.push_back(160);
v8.push_back(180);
v8.push_back(200);
vector<int> v9;
v9.push_back(10);
v9.push_back(120);
v9.push_back(150);
if (v8 == v9) // 원소 갯수, 원소값이 모두 일치해야 출력
cout << "v1 == v2" << endl;
if (v8 != v9) // 모든 원소가 같은게 아니면 출력
cout << "v1 != v2" << endl;
if (v8 < v9) // 원소 하나하나 비교해서 v9 원소가 크면 true
cout << "v1 < v2" << endl;
return 0;
}
'Study > STL' 카테고리의 다른 글
STL 06. 시퀀스 컨테이너 (List) (0) | 2021.12.02 |
---|---|
STL 06. 시퀀스 컨테이너 (Deque) (0) | 2021.12.02 |
STL 01. 연산자 오버로딩(3) (0) | 2021.10.30 |
STL 01. 연산자 오버로딩 (2) const 멤버 함수와 비 const 멤버 함수 (0) | 2021.10.27 |
STL 01. 연산자 오버로딩 (1) (0) | 2021.10.27 |