C++ 초급 - 6. 배열과 문자열 (3 - std::vector)

2025. 2. 22. 13:35프로그래밍 언어/C++

📌 6.3 std::vector (C++98부터 사용 가능)

C++의 std::vector배열의 단점을 보완한 동적 크기 조절이 가능한 컨테이너이다.
배열(int arr[5];)은 고정된 크기를 가지지만, std::vector는 필요에 따라 크기가 자동으로 조절됨.
또한 안전한 메모리 관리 및 편리한 기능 제공(push_back, size, at 등)으로 효율적인 데이터 관리를 가능하게 한다.

std::vector는 <vector> 헤더를 포함하여 사용 가능하다.


📌 1. std::vector 선언 및 초기화

🔹 (1) std::vector 기본 선언

💡 기본 문법

#include <vector>
std::vector<데이터타입> 변수명;

💡 예제: std::vector 선언 및 초기화

#include <iostream>
#include <vector>

int main() {
    std::vector<int> v1;  // 비어있는 벡터 선언
    std::vector<int> v2(5);  // 크기가 5인 벡터 (기본값 0으로 초기화)
    std::vector<int> v3 = {1, 2, 3, 4, 5};  // 리스트 초기화
    std::vector<int> v4(3, 10);  // 크기가 3이고, 모든 요소가 10으로 초기화

    std::cout << "v3의 첫 번째 요소: " << v3[0] << std::endl;  // 1

    return 0;
}

🔹 출력 결과

v3의 첫 번째 요소: 1

💡 설명

  • std::vector<int> v1; → 크기가 0인 벡터.
  • std::vector<int> v2(5); → 크기가 5이고 모든 값이 0으로 초기화.
  • std::vector<int> v3 = {1, 2, 3, 4, 5}; → 리스트 초기화.
  • std::vector<int> v4(3, 10); → 크기가 3이며 모든 요소가 10.

📌 2. push_back, size, at 등의 기본적인 기능

🔹 (1) push_back(): 벡터에 요소 추가

  • push_back(값)을 사용하면 벡터의 마지막에 요소를 추가할 수 있다.

💡 예제: push_back 사용

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec;
    
    vec.push_back(10);
    vec.push_back(20);
    vec.push_back(30);

    std::cout << "벡터 크기: " << vec.size() << std::endl;  // 3
    std::cout << "벡터 마지막 요소: " << vec.back() << std::endl;  // 30

    return 0;
}

🔹 출력 결과

벡터 크기: 3
벡터 마지막 요소: 30

💡 설명

  • push_back(10); → 벡터 끝에 10을 추가.
  • vec.size(); → 현재 벡터 크기 반환.
  • vec.back(); → 벡터의 마지막 요소 반환.

🔹 (2) size(): 벡터 크기 확인

  • size()는 현재 벡터에 저장된 요소의 개수를 반환한다.

💡 예제: 벡터 크기 확인

std::vector<int> v = {1, 2, 3};
std::cout << "벡터 크기: " << v.size() << std::endl;

🔹 출력 결과

벡터 크기: 3

🔹 (3) at(): 안전한 요소 접근

  • at(index)는 배열처럼 요소에 접근하지만, 범위를 벗어나면 예외를 발생시킨다.

💡 예제: at() 사용

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {10, 20, 30};

    std::cout << "첫 번째 요소: " << vec.at(0) << std::endl;  // 10

    try {
        std::cout << vec.at(5) << std::endl;  // ❌ 예외 발생 (잘못된 인덱스 접근)
    } catch (const std::out_of_range& e) {
        std::cout << "예외 발생: " << e.what() << std::endl;
    }

    return 0;
}

🔹 출력 결과

첫 번째 요소: 10
예외 발생: vector::_M_range_check: __n (which is 5) >= this->size() (which is 3)

💡 설명

  • vec.at(0); → 첫 번째 요소(10) 출력.
  • vec.at(5); → 범위를 벗어난 접근으로 예외 발생.

📌 3. 반복문을 이용한 std::vector 순회

벡터는 배열과 유사하게 for 문을 사용하여 순회 가능하다.
또한 **C++11 이상의 범위 기반 for 문(range-based for loop)**을 사용할 수도 있다.

💡 예제: 벡터 순회

#include <iostream>
#include <vector>

int main() {
    std::vector<int> vec = {10, 20, 30, 40, 50};

    // 일반 for 문
    std::cout << "일반 for 문 사용: ";
    for (size_t i = 0; i < vec.size(); i++) {
        std::cout << vec[i] << " ";
    }
    std::cout << std::endl;

    // 범위 기반 for 문 (C++11 이상)
    std::cout << "범위 기반 for 문 사용: ";
    for (int val : vec) {
        std::cout << val << " ";
    }
    std::cout << std::endl;

    return 0;
}

🔹 출력 결과

일반 for 문 사용: 10 20 30 40 50
범위 기반 for 문 사용: 10 20 30 40 50

💡 설명

  • for (size_t i = 0; i < vec.size(); i++) → 일반 for 문 사용.
  • for (int val : vec) → C++11 이상의 범위 기반 for 문으로 간결한 코드 가능.

📌 4. 동적 크기 조절과 메모리 관리의 차이점

🔹 (1) 배열 vs 벡터 메모리 관리 차이

비교 항목 배열 (int arr[10];) 벡터 (std::vector v;)
크기 조정 변경 불가능 동적 크기 조절 가능
메모리 할당 스택(Stack) 사용 힙(Heap) 사용
배열 크기 초과 접근 위험 (쓰레기 값 or 충돌) at() 사용 시 예외 발생
메모리 해제 자동 해제 자동 해제 (delete 필요 없음)

💡 배열은 크기가 고정되지만, std::vector는 push_back()을 통해 크기 확장 가능.


📌 5. 정리

개념 설명
벡터 선언 std::vector<int> v;
요소 추가 push_back(값);
크기 확인 size();
안전한 요소 접근 at(index);
반복문을 이용한 순회 일반 for 문 또는 범위 기반 for 문 활용
배열과 차이점 크기 동적 조절 가능, 자동 메모리 관리, 안전한 요소 접근