C++ 프로그래밍을 하다 보면 함수가 배열 전체를 반환하도록 작성하고 싶은 경우가 있습니다. 하지만 C++는 배열을 직접 반환하는 것을 지원하지 않는데, 그 이유를 다음 예제 코드를 통해 살펴보겠습니다.
문제가 되는 예제 코드
#include <iostream>
using namespace std;
int* Array() {
int a[100];
a[0] = 7;
a[1] = 6;
a[2] = 4;
a[3] = 3;
return a; // 지역 변수의 주소를 반환
}
int main() {
int* p = Array();
cout << p[0] << " " << p[1] << " " << p[2] << " " << p[3];
return 0;
}이 코드를 컴파일하면 다음과 같은 경고 메시지가 출력됩니다.
컴파일러 경고
In function 'int* Array()': warning: address of local variable 'a' returned [-Wreturn-local-addr] int a[100];
왜 이런 문제가 발생할까요?
핵심 원인은 지역 변수의 생명주기(lifetime)에 있습니다. 함수 내부에서 선언된 배열 a는 스택(stack) 메모리에 할당되며, 해당 함수의 호출이 종료되는 순간 함께 소멸됩니다.
즉, Array() 함수가 값을 반환하는 시점에는 이미 배열 a가 차지하던 메모리 공간이 해제되어 유효하지 않은 상태가 됩니다. 따라서 그 주소를 받아 사용하는 main 함수 쪽에서는 정의되지 않은 동작(undefined behavior)이 발생하게 됩니다. 운이 좋으면 값이 출력될 수도 있지만, 언제든 덮어써진 garbage 값이 나올 수 있으므로 절대 의존해서는 안 됩니다.
결국 C++가 함수의 배열 직접 반환을 지원하지 않는 이유는 함수 종료 후 지역 변수가 메모리에서 사라지기 때문입니다.
그렇다면 배열 데이터를 반환하려면 어떻게 해야 할까?
배열 형태의 데이터를 함수 외부로 전달해야 한다면 다음과 같은 안전한 방법들을 사용할 수 있습니다.
1. 정적(static) 변수 활용
int* Array() {
static int a[100];
a[0] = 7;
return a;
}2. 동적 메모리 할당(new)
int* Array() {
int* a = new int[100];
a[0] = 7;
return a; // 호출자가 delete[]로 해제 필요
}3. std::vector 또는 std::array 사용 (권장)
현대 C++에서는 값 복사가 자연스럽게 처리되는 std::vector<int>나 std::array<int, 100>를 반환하는 것이 가장 안전하고 관용적인 방법입니다.
정리하자면, C++는 스택 기반 지역 배열의 특성상 배열 자체를 반환할 수 없으며, 포인터 반환 역시 위험하기 때문에 컨테이너 타입을 활용한 설계가 바람직합니다.