Vector
다양한 자료형을 저장할 수 있는 배열로, 길이 변경이 가능하다. 즉, 원소가 추가되거나 삽입될 경우 메모리 재할당이 발생할 수 있다. 이때 cost가 크므로, 선언 시 충분한 메모리를 확보해 놓아야 한다. 이때는 reserve() 혹은 assign()을 활용한다.
아래는 Vector 사용법의 예시다.
#include <iostream>
#include <vector>
using namespace std;
void print(vector<int> &a);
int main() {
//선언
vector<int> v1;
vector<int> v2(10);
vector<int> v3(15, 1);
vector<int> v4 = { 1, 2, 3, 4, 5 };
vector<vector<int>> v5;
int n = 10, m = 20;
vector<vector<int>> v6(n, vector<int>(m));
//활용
vector<int> a = { 1, 2, 3, 4, 5 };
a.push_back(6); // [1, 2, 3, 4, 5, 6]
a.push_back(7); // [1, 2, 3, 4, 5, 6, 7]
a.pop_back(); // [1, 2, 3, 4, 5, 6]
a.pop_back(); // [1, 2, 3, 4, 5]
a.pop_back(); // [1, 2, 3, 4]
a.clear(); // []
a.resize(5); // [0, 0, 0, 0, 0]
a.clear(); // []
a.push_back(1); // [1]
a.push_back(2); // [1, 2]
a.resize(5); // [1, 2, 0, 0, 0]
a.resize(3); // [1, 2, 0]
a.clear(); // []
//----------------------------------------------//
a = { 1, 2, 3, 4 };
cout << "size = " << a.size() << '\n'; // 4
a.push_back(5);
cout << "size = " << a.size() << '\n'; // 5
cout << "empty = " << a.empty() << '\n'; // 0 (false)
a.clear();
cout << "size = " << a.size() << '\n'; // 0
cout << "empty = " << a.empty() << '\n'; // 1 (true)
a = { 1, 2, 3 };
cout << "front = " << a.front() << '\n'; // 1
cout << "a[1] = " << a[1] << '\n'; // 2
cout << "back = " << a.back() << '\n'; // 3
//----------------------------------------------//
for (int i = 0; i<a.size(); i++) { // 전체 출력 방법 1
cout << a[i] << ' ';
}
cout << '\n';
for (int &x : a) { // 전체 출력 방법 2 (reference 활용)
cout << x << ' ';
}
cout << '\n';
for (vector<int>::iterator it = a.begin(); it != a.end(); ++it) { // 전체 출력 방법 3 (Iterator 활용)
cout << *it << ' ';
}
cout << '\n';
for (auto it = a.begin(); it != a.end(); ++it) { // 전체 출력 방법 4 (auto 활용)
cout << "a[" << (it - a.begin()) << "] = " << *it << '\n';
}
//----------------------------------------------//
a = { 1, 2, 3 };
print(a); // 1 2 3
auto it = a.begin(); // begin()은 첫번째 데이터의 포인터를 반환
a.insert(it, 4); // it 앞에 4를 삽입, 함수는 삽입한 원소의 반복자를 리턴
print(a); // 4 1 2 3
it = a.begin() + 1; // begin()+1은 두번째 데이터의 포인터를 반환
a.insert(it, 5, 0); // it 앞에 0을 5개 삽입
print(a); // 4 0 0 0 0 0 1 2 3
it = a.begin() + 2;
vector<int> b = { 10, 20, 30};
a.insert(it, b.begin(), b.end()); // it 앞에 [b.begin(), b.end()) 삽입
print(a); // 4 0 10 20 30 0 0 0 0 1 2 3
//----------------------------------------------//
a = { 1, 2, 3 };
it = a.begin();
a.erase(it); // it가 가리키는 원소를 제거, 함수는 it의 다음 원소를 가리키는 반복자를 리턴
print(a); // 2 3
a = { 1, 2, 3 };
it = a.begin();
auto it2 = a.begin()+2;
a.erase(it, it2); // [it, it2)의 원소를 제거, 함수는 다음 원소를 가리키는 반복자를 리턴
print(a); // 3
//----------------------------------------------//
vector<int> c = { 1, 2, 3};
cout << c.capacity() << '\n'; // 3
print(c); // 1 2 3
c.reserve(10); // 10개의 원소가 들어갈 수 있도록 크기를 확보
cout << c.capacity() << '\n'; // 10
print(c); // 1 2 3
//----------------------------------------------//
vector<int> d;
d.assign(50, 0); // 50개의 0으로 초기화
cout << d.capacity() << '\n'; // 50
return 0;
}
void print(vector<int> &a) {
for (int x : a) {
cout << x << ' ';
}
cout << '\n';
}
주요 멤버 함수를 다음과 같이 요약할 수 있다.
vector<int> a = { 1, 2, 3, 4, 5 };
a.push_back(6); // [1, 2, 3, 4, 5, 6]
a.pop_back(); // [1, 2, 3, 4, 5]
cout << "front = " << a.front() << '\n'; // 1
cout << "back = " << a.back() << '\n'; // 5
a.clear(); // []
a.resize(5); // [0, 0, 0, 0, 0]
for (int i = 0; i<a.size(); i++) {
cout << a[i] << ' ';
}
cout << '\n';
vector<char>::iterator it = a.begin();
a.insert(it, 4); // it 앞에 4를 삽입, 함수는 삽입한 원소의 반복자를 리턴
a.erase(it); // it가 가리키는 원소를 제거, 함수는 it의 다음 원소를 가리키는 반복자를 리턴
a.reserve(10); // 10개의 원소가 들어갈 수 있도록 크기를 확보
a.assign(50, 0); // 50개의 0으로 초기화