Vector Container
기술노트
C++ Vector 컨테이너
Vector는 C++ STL에서 제공하는 동적 배열 컨테이너로, 자동으로 메모리를 할당하고 관리합니다. 데이터 타입을 템플릿 매개변수로 지정할 수 있으며, 스택과 유사한 push/pop 연산을 지원합니다.
기본 개념
Vector는 연속된 메모리 공간에 원소를 저장하며, 크기가 동적으로 조절됩니다. 내부적으로는 다음 두 가지 중요한 속성을 관리합니다:
- size: 실제로 저장된 원소의 개수
- capacity: 메모리에 할당된 공간의 크기
Vector의 크기가 capacity를 초과하면 더 큰 메모리 공간을 할당하고 기존 요소를 복사하는 재할당(reallocation) 과정이 발생합니다.
헤더 파일 포함
#include <vector>
선언 및 초기화
// 빈 벡터 생성
vector<int> v1;
// 특정 값으로 초기화된 벡터 생성 (5개의 2로 초기화)
vector<int> v2(5, 2); // {2, 2, 2, 2, 2}
// 다른 벡터의 복사본 생성
vector<int> v3(v2);
// 초기화 리스트 사용
vector<int> v4 = {1, 2, 3, 4, 5};
// 특정 범위의 요소로 초기화
vector<int> v5(v4.begin(), v4.begin() + 3); // {1, 2, 3}
주요 멤버 함수
요소 접근
// 인덱스로 접근 (범위 검사 없음, 빠름)
int elem1 = v[0];
// 안전한 접근 방법 (범위 검사 있음, 예외 발생 가능)
int elem2 = v.at(0);
// 첫 번째와 마지막 요소 접근
int first = v.front();
int last = v.back();
요소 추가 및 삭제
// 끝에 요소 추가
v.push_back(6);
// 끝에서 요소 제거
v.pop_back();
// 특정 위치에 요소 삽입 (iterator 필요)
v.insert(v.begin() + 2, 10); // 세 번째 위치에 10 삽입
// 특정 위치의 요소 삭제 (iterator 필요)
v.erase(v.begin() + 1); // 두 번째 요소 삭제
// 모든 요소를 특정 값으로 할당
v.assign(5, 2); // {2, 2, 2, 2, 2}
// 모든 요소 제거 (capacity는 유지)
v.clear();
크기 및 용량 관리
// 현재 요소 개수 확인
size_t size = v.size();
// 할당된 메모리 공간 크기 확인
size_t cap = v.capacity();
// 비어있는지 확인
bool isEmpty = v.empty();
// 크기 변경 (필요시 요소 추가 또는 제거)
v.resize(10); // 크기를 10으로 변경
// 최소 용량 확보 (필요시에만 재할당)
v.reserve(100); // 최소 100개 요소를 저장할 공간 확보
// 여분의 용량 제거
v.shrink_to_fit();
반복자(Iterator) 사용
반복자는 컨테이너의 요소를 순회하는 데 사용됩니다.
// 기본 for 루프 예제
vector<int>::iterator iter;
for(iter = v.begin(); iter != v.end(); iter++) {
cout << *iter << endl;
}
// 범위 기반 for 루프 (C++11 이상)
for(const auto& elem : v) {
cout << elem << endl;
}
// 역방향 반복자
for(auto rit = v.rbegin(); rit != v.rend(); ++rit) {
cout << *rit << endl; // 역순으로 출력
}
알고리즘과 함께 사용
<algorithm>
헤더와 함께 사용하면 다양한 연산을 효율적으로 수행할 수 있습니다.
#include <algorithm>
// 정렬
sort(v.begin(), v.end());
// 역순 정렬
sort(v.begin(), v.end(), greater<int>());
// 특정 값 찾기
auto it = find(v.begin(), v.end(), 3);
if(it != v.end()) {
cout << "값 3을 찾았습니다! 위치: " << (it - v.begin()) << endl;
}
// 요소 개수 세기
int count_of_twos = count(v.begin(), v.end(), 2);
성능 특성
- 임의 접근: O(1)
- 끝에 요소 추가/제거: 상환 O(1)
- 중간에 요소 삽입/제거: O(n)
- 검색: O(n)
Vector는 임의 접근이 빈번하거나 끝에서의 삽입/삭제가 주로 필요한 경우 효율적인 자료구조입니다.
실제 사용 예제
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
int main() {
// 문자열 vector 생성
vector<string> names = {"Kim", "Park", "Lee"};
// 요소 추가
names.push_back("Choi");
names.push_back("Jung");
// 정렬
sort(names.begin(), names.end());
// 출력
cout << "이름 목록 (알파벳 순):" << endl;
for(const auto& name : names) {
cout << name << endl;
}
// 특정 요소 검색
string search_name = "Park";
auto it = find(names.begin(), names.end(), search_name);
if(it != names.end()) {
cout << search_name << "은(는) 목록의 "
<< (it - names.begin() + 1) << "번째에 있습니다." << endl;
} else {
cout << search_name << "은(는) 목록에 없습니다." << endl;
}
return 0;
}
주의사항
- Iterator Invalidation: vector의 크기를 변경하는 작업(push_back, resize 등)은 반복자를 무효화할 수 있습니다.
- 재할당: capacity를 초과하면 메모리 재할당이 발생하여 성능에 영향을 줄 수 있습니다. 필요한 경우 미리
reserve()
를 호출하세요. - 잘못된 접근:
[]
연산자는 범위 검사를 하지 않으므로 주의해야 합니다. 안전한 접근이 필요하면at()
메서드를 사용하세요.