Computer >> 컴퓨터 >  >> 프로그래밍 >> C++

C++ 함수에서 배열을 반환하는 방법 – 포인터와 static 변수 활용

C++에서는 배열 전체를 그대로 반환할 수 없습니다. 대신 배열의 첫 번째 요소를 가리키는 포인터를 반환하는 방식으로 이를 구현합니다.

여기서 주의할 점이 있습니다. 함수 내부에서 선언된 일반 지역 변수는 함수가 종료되는 순간 스택에서 소멸하기 때문에, 그 주소를 외부로 반환하면 댕글링 포인터(dangling pointer)가 되어 심각한 오류를 일으킬 수 있습니다. 이를 해결하려면 지역 변수를 static으로 선언해야 합니다. static 변수는 프로그램이 종료될 때까지 메모리에 유지되므로, 함수가 끝난 후에도 해당 주소를 안전하게 사용할 수 있습니다.

포인터 반환 기본 문법

int* function_name() {
    // body
}
  • function_name − 사용자가 정의하는 함수 이름입니다.
  • 반환 타입이 int*이므로 int형 배열의 시작 주소를 반환할 수 있습니다.

예제 코드

다음은 함수에서 배열을 반환하는 예제입니다.

#include <iostream>
using namespace std;

int* ret() {
    static int x[5];  // static 배열: 프로그램 종료 시까지 유지됨
    for(int i = 0; i < 5; i++) {
        cout << " " << &x[i];
    }
    return x;
}

int main() {
    ret();
    return 0;
}

실행 결과

0x601180 0x601184 0x601188 0x60118c 0x601190

코드 설명

위 프로그램에서는 ret()이라는 함수를 만들어 배열을 반환하도록 작성했습니다. 함수 내부에서 static int 타입의 배열 x를 선언하고, 할당된 메모리 블록들의 주소를 출력한 뒤 배열 x를 반환합니다.

int* ret() {
    static int x[5];
    for(int i = 0; i < 5; i++) {
        cout << " " << &x[i];
    }
    return x;
}

main() 함수에서는 다음과 같이 ret() 함수를 호출합니다.

ret();

출력 결과를 보면 각 요소의 주소가 4바이트(int 크기)씩 증가하는 것을 확인할 수 있습니다. 이는 배열의 요소들이 메모리상에 연속적으로 배치되어 있음을 보여줍니다.

더 안전한 대안: std::array와 std::vector

원시 배열과 포인터 반환은 배열 크기 정보가 사라지고 메모리 수명을 직접 관리해야 하는 등 실수하기 쉬운 방식입니다. 현대 C++에서는 다음과 같은 컨테이너 사용을 권장합니다.

  • std::array − 크기가 고정된 배열을 값처럼 자유롭게 반환할 수 있습니다.
  • std::vector − 크기가 동적으로 변하는 배열을 안전하게 반환합니다.
#include <vector>
using namespace std;

vector<int> getNumbers() {
    vector<int> v = {1, 2, 3, 4, 5};
    return v;
}

이러한 컨테이너는 복사 및 이동 의미론(move semantics)을 지원하므로 메모리 해제나 댕글링 포인터를 걱정할 필요 없이 훨씬 안전하게 배열 데이터를 주고받을 수 있습니다.