2021. 4. 6. 14:33ㆍ개발 관련/c++
Vector은 java의 ArrayList와 비슷하다.
add, remove 등의 명령어 한 줄만 적으면 알아서 사이즈를 줄여준다.
근데 for문이 돌면서 찾아주는걸까?
요약
저장할 데이터 개수가 가변적일 때,
중간에 삽입과 삭제가 없을 때 사용 ( 범위 검사할 필요가 없기 때문에 v.at(i) 대신에 v[i]를 사용하였다. )
삽입과 삭제가 빈번할 때는 list나 deque를 사용하자.
#include <vector>
#include <iostream>
void swap(int i, int j, vector<int> &v) {
int temp = v[i];
v[i] = v[j];
v[j] = temp;
}
void main() {
vector<int> v(10, 0); // 10 크기 할당, 모두 0으로 초기화
v.emplace(v.begin()+1, 1); // 첫번째 인덱스에 1 추가
// [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
v.size(); // size = 11, capacity는 환경에 따라 다름
v.pop_back(); // [0, 1, 0, 0, 0, 0, 0, 0, 0, 0]
v.size(); // size = 10
v.reserve(20); // capacity = 20 ( 최대 할당 크기 )
v.push_back(2); // [0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2]
swap(1, 2, v); // [0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 2]
cout << v[0] << endl; // 0
cout << *(v.begin()) << endl; // 0
count << *(v.end()-1) << endl; // 2
}
vector 선언 및 초기화
void main() {
vector<int> vec1; // 비어있는 vector 생성
vec1.assign(10, 1); // vec1의 10 크기(0~9)에 1로 초기화
vector<int> vec2(10); // 10개의 크기(capacity)를 할당 받음. 0으로 초기화
vec2.assign(5, 10); // vec2의 0~4까지 10으로 초기화
vector<int> vec3(10, 3); // 10개의 크기를 할당받음. 3으로 초기화
vector<int> vec4 = {10, 10, 10, 5, 5, 4}; // 오른쪽의 변수로 초기화
vector<int> vec5[] = {{1, 10}, {2, 5], {3, 4}}; // 2차원 배열 벡터. 행 가변, 열 고정
vector<int> vec6(v3); // vec3를 복사
}
vector 값 추가
void main() {
vector<int> vec1; // 비어있는 vector 생성
vec1.push_back(10); // 마지막에 추가 ( vec1[size++] = 10; )
// [ 10 ]
vec1.insert(vec1.begin(), 2 ) // vec1의 0번째에 2를 추가, 복사생성자 호출
// [ 2, 10 ]
vec1.insert(vec1.begin()+1, 3 ) // vec1의 1번째에 3을 추가
// [ 2, 3, 10 ]
vec1.emplace(vec1.begin()+1, 4) // vec1의 1번째에 4를 추가, 벡터 내부에서 값 생성
// [ 2, 4, 3, 10 ]
vec1.emplace_back(5); // vec1의 마지막에 5 추가
// [ 2, 4, 3, 10, 5 ]
}
※ insert와 emplace 차이 -> emplace 사용을 권장
insert는 모든 값들을 메모리에 복사한 후 값을 넣는다. (복사생성자 호출. array의 끼워넣기 -> 오버헤드, 성능 저하)
emplace는 벡터 내부에서 값을 생성 (템플릿 <T>에 대한 생성자만 호출)
vector 값 삭제
void main() {
vector<int> vec1 = { 2, 4, 3, 10, 5 };
vec1.pop_back(); // 맨 끝의 값 제거 ( vec1[size--] = null; }
// [ 2, 4, 3, 10 ]
vec1.erase(v.begin()) // 0번째 값 제거, O(n) : 뒤에서 하나씩 당겨서 저장
// [ 4, 3, 10 ]
vec1.erase(v.begin(), v.begin() + 2); // 0번째부터 1번째 값 지우기 ( 총 두개)
// [ 10 ]
vec1.clear(); // 모든 요소를 지운다. return size;( size = 0 , capacity = 5 )
vector<int>().swap(vec1); // 빈 vector(capacity=0)와 vec1를 바꾼다. 메모리 절약
vec1.capacity(); // capacity = 0
}
vector 값 검색 - []를 추천
#include <iostream>
#include <vector>
#include <algorithm>
void main() {
vector<int> v = { 0, 1, 2, 3, 4, 5 };
v.at(1); // 1 ( 범위 검사 o, 범위 밖일 경우 예외처리 발생 - std::out_of_range )
v[1]; // 1 ( 범위 검사 x ), []를 권장
v.front(); // 0
v.back(); // 5
for_each(v.begin(), v.end(), [&](int& n) { // v.end()는 null값의 주소값, 마지막 값 출력하고 싶을 때 *(v.end()-1)로 해야함
cout << n << endl; // 0, 1, 2, 3, 4, 5
});
for_each(v.rbegin(), v.rend(), [&](int& n) { // reverse
cout << n << endl; // 5, 4, 3, 2, 1, 0
});
/* iterator 이용 */
vector<int>::iterator itor = v.begin();
for (; itor != v.end(); itor++)
cout << *itor << endl; // 0, 1, 2, 3, 4, 5
vector<int>::reverse_iterator itor2 = v.rbegin();
for (; itor2 != v.rend(); itor2++)
cout << *itor2 << endl; // 5, 4, 3, 2, 1, 0
}
vector 메모리 공간 관리
void main() {
vector<int> v(10, 0); // 10 크기 할당, 모두 0으로 초기화
v.size(); // size = 10, capacity는 환경에 따라 다름
v.reserve(20); // capacity = 20 ( 할당 크기 지정 )
v.capacity(); // 20, 할당된 공간 크기
v.max_size(); // system에서 만들어질 수 있는 최대 크기 반환
v.shrink_to_fit(); // 10, capacity = size; 남은 공간 없애줌
vector<int>().swap(v); // 빈 vector와 v를 교환. 메모리 절약 ( capacity = 0 )
}
※ size와 capacity -> emplace 사용을 권장
size : 벡터가 생성된 크기 ( 값이 들어가있는 크기 )
capacity : 할당된 벡터의 공간 크기 ( 메모리에 차지하는 벡터의 크기 )
-> 벡터의 크기가 capacity를 초과하면 재할당(re-allocation) 발생 ( 성능 저하 )
-> 모든 값들을 새로운 메모리 공간에 복사한 후 기존 벡터 파괴
재할당을 줄이기 위해서 reserve()를 통해 capacity 크기를 설정하자. ( 너무 크게 잡을 경우 메모리 낭비 )
shrink_to_fit()를 통해 capacity=size 가능
clear()의 경우 값이 지워질 뿐 공간은 남아있다.(size == 0, capacity == 기존크기, 메모리 낭비 )
swap을 이용하여 메모리 free 해주자. ( 사실 함수가 끝나면 자동으로 힙에서 메모리 해제가 되니 특수한 경우에 사용. )
vector의 call by value ( 값에 의한 호출 - get 가능, set 불가 )
void swap(int i, int j, vector<string> v ) { // &로 vector를 받자 ( v가 array이다. )
string temp = v[i];
v[i] = v[j];
v[j] = temp;
}
void main() {
vector<string> vec1 = {... };
...
swap(i, j, vec1); // vec1의 i, j번째를 바꾸기. vec1의 주소값을 넘김(전체를 넘김)
...
}
vector의 call by reference ( 참조에 의한 호출 - get과 set 모두 가능 )
void swap(int i, int j, vector<string> &v ) { // &로 vector를 받자 ( v가 array이다. )
string temp = v[i];
v[i] = v[j];
v[j] = temp;
}
void main() {
vector<string> vec1 = {... };
...
swap(i, j, vec1); // vec1의 i, j번째를 바꾸기. vec1의 주소값을 넘김(전체를 넘김)
...
}
참고 사이트
insert와 emplace 차이 : hwan-shell.tistory.com/119
call by reference : soyoonique.tistory.com/32
'개발 관련 > c++' 카테고리의 다른 글
[C++] 배열 초기화(-1로 초기화), call by value, pointer, reference (0) | 2021.04.06 |
---|