Vector Container

기술노트
Admin (토론 | 기여)님의 2025년 4월 21일 (월) 13:56 판

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;
}

주의사항

  1. Iterator Invalidation: vector의 크기를 변경하는 작업(push_back, resize 등)은 반복자를 무효화할 수 있습니다.
  2. 재할당: capacity를 초과하면 메모리 재할당이 발생하여 성능에 영향을 줄 수 있습니다. 필요한 경우 미리 reserve()를 호출하세요.
  3. 잘못된 접근: [] 연산자는 범위 검사를 하지 않으므로 주의해야 합니다. 안전한 접근이 필요하면 at() 메서드를 사용하세요.

참고 자료