HOWTO · C++

포인터에서 C++의 벡터로 멤버 함수 액세스

C++에서 포인터를 통해 std::vector 멤버를 호출하는 방법, 벡터 포인터를 함수에 전달하는 방법, 그리고 그 요소를 순회하는 방법을 알아보세요.

이 페이지의 내용

C++ 벡터의 멤버를 포인터를 통해 호출하려면 ptr->member를 사용합니다. 이에 해당하는 다른 표기법은 (*ptr).member입니다. 포인터는 벡터 요소가 아니라 벡터 객체 자체를 가리켜야 합니다. &를 사용해 해당 객체의 주소를 얻은 다음, 두 표현식 중 하나로 size()나 at() 같은 멤버를 사용하세요. 아래 예제에서는 포인터를 함수에 전달하고, 이를 통해 각 값도 읽습니다.

포인터를 통해 ->로 벡터에 접근하기

벡터 타입 뒤에 *를 붙여 포인터를 선언합니다. 정수 벡터의 타입은 std::vector<int>*입니다. values가 이미 존재하는 벡터라면 &values는 그 주소입니다. 이 주소를 포인터에 대입하면 포인터가 해당 벡터를 가리킵니다. 이렇게 해도 벡터가 복사되거나 별도의 컬렉션이 만들어지지는 않습니다.

화살표 연산자는 포인터 역참조와 멤버 선택을 결합합니다. 따라서 ptr->size()는 ptr이 가리키는 벡터에서 size()를 호출합니다. 같은 포인터를 이에 맞는 포인터 타입의 매개변수를 받는 함수에 전달할 수도 있습니다. 전체 예제에서 report_size는 벡터를 읽기만 하므로 const 벡터를 가리키는 포인터를 받습니다. const 지정은 함수가 매개변수를 통해 벡터를 수정하지 못하게 합니다. 포인터를 전달하는 방식은 바뀌지 않습니다.

이 예제를 실행해 보세요.

#include <cstddef>
#include <iostream>
#include <vector>

void report_size(const std::vector<int>* ptr) {
    std::cout << "Count: " << ptr->size() << '\n';
}

int main() {
    std::vector<int> values{10, 20, 30};
    const std::vector<int>* ptr = &values;

    report_size(ptr);
    for (std::size_t i = 0; i < ptr->size(); ++i) {
        std::cout << (*ptr).at(i) << '\n';
    }
}
Count: 3
10
20
30

실행하면 벡터의 크기가 출력된 다음 각 값이 한 줄씩 출력됩니다. 벡터는 자동 저장 기간을 갖는 지역 변수이며, 포인터는 벡터가 유효한 범위 안에서만 사용됩니다. 직접 작성하는 프로그램에서도 포인터가 주소를 저장한 객체보다 오래 살아남지 않도록 하세요.

포인터를 통해 (*ptr).member로 벡터에 접근하기

(*ptr).member 표현식은 먼저 ptr을 역참조해 벡터 객체를 얻고, 그다음 .으로 객체의 멤버를 선택합니다. 괄호가 중요합니다. 괄호가 없으면 의도한 연산과 달리 역참조하기 전에 점 연산자가 ptr에 적용됩니다. 벡터 멤버의 경우 (*ptr).size()와 ptr->size()는 같은 뜻입니다. 화살표 표기가 더 짧고, 역참조 후 점을 사용하는 표기는 두 연산을 명시적으로 보여 줍니다.

위 예제의 (*ptr).at(i)는 벡터 포인터를 역참조한 뒤 인덱스로 요소에 접근합니다. 멤버 호출은 벡터에서 이루어지며, at(i)는 선택된 정수 요소를 참조합니다. 코드를 읽을 때 이 차이를 기억하면 유용합니다. ptr의 타입은 벡터 포인터지만, (*ptr).at(i)는 요소 값에 접근하는 표현식이지 요소를 가리키는 포인터가 아닙니다. 함수가 벡터를 다뤄야 한다면 벡터 포인터를 전달하고, 요소 하나를 다뤄야 한다면 요소 참조나 적절한 요소 포인터를 사용하세요.

벡터 포인터를 통해 요소 순회하기

반복문은 ptr->size()를 종료 조건으로 사용하고, (*ptr).at(i)로 각 값에 접근합니다. 두 연산 모두 벡터 포인터를 거칩니다. 인덱스로 멤버를 호출할 때는 화살표 표기인 ptr->at(i)를 사용할 수도 있습니다. 같은 벡터 멤버를 선택합니다. <cstddef>에서 포함하는 std::size_t는 벡터의 크기와 인덱스에 적합한 부호 없는 타입입니다.

벡터 포인터는 벡터 반복자나 개별 요소를 가리키는 포인터와 다릅니다. 이 예제의 포인터는 std::vector<int> 객체 전체를 가리킵니다. 반복자는 컨테이너가 제공하는 요소 순회 위치이고, 요소 포인터는 저장된 값 하나를 가리킵니다. 인덱스 기반 반복문은 이 역할들을 구분해 보여 주며, 인덱스가 필요할 때 유용합니다. 모든 값을 방문하기만 하면 *ptr을 대상으로 범위 기반 반복문을 사용할 수도 있습니다. 다만 이 방식은 매 단계마다 포인터를 통한 멤버 접근을 보여 주는 대신 벡터를 순회합니다.

예제에서는 순회 중에 벡터를 변경하지 않으므로 인덱스를 사용한 접근이 간단합니다. 순회 중 요소를 삽입하거나 제거하는 프로그램에서는 반복문을 다시 검토하세요. 이러한 작업은 벡터의 크기를 바꿀 수 있고 요소를 가리키는 참조, 포인터 또는 반복자를 무효화할 수 있습니다. 벡터 객체를 가리키는 포인터는 계속 그 객체를 가리키지만, 요소의 위치까지 안정적으로 유지해 주지는 않습니다. 포인터를 사용할 때마다 벡터가 살아 있도록 하고, 프로그램에서 수행하는 변경을 고려해 순회 로직을 선택하세요.