C++에서 함수는 포인터들도 리턴할 수 있습니다.
그러한 함수들은
type *funcion();
의 형태로 선언됩니다.
한가지 중요한 점은 '절대로 함수 내의 로컬 변수를 리턴하지 않는다.' 입니다.
간단한 예시 코드를 살펴보겠습니다.
int *largest_int(int *int_ptr1, int *int_ptr2){
if (*int_ptr1 > *int_ptr2)
return int_ptr1;
else
return int_ptr2;
}
두개의 정수 포인터를 비교하여 더 큰 값의 정수의 포인터를 반환합니다.
이 함수를 사용하는 메인 함수의 예시는 다음과 같을 수 있습니다.
int main() {
int a {30};
int b {40};
int *largest_ptr{nullptr};
largest_ptr = largest_int(&a, &b);
cout << *largest_ptr << endl; // 40
// or
int a{30};
int b{50};
int *largest_ptr = {largest_int(&a, &b)};
cout << *largest_ptr << endl; // 50
return 0;
}
중요한 점은 &를 활용하여 pass by reference를 한 것과,
함수 내에서 비교한 것은 포인터의 값이 아닌, 포인터 값의 값이라는 점 입니다.
배열에 대한 함수로 한 가지 더 코드를 보여드리겠습니다.
int *create_arr(size_t size, int init_val=0){
int *new_arr = new int[size]; // 배열 생성
for (size_t i{0}; i < size; i++){
*(new_arr + i) = init_val; // 초기화
}
return new_arr; // 리턴
}
int main() {
int *my_arr {create_arr(10, 50)}; // 길이 10의 50으로 초기화된 배열에 대한 포인터
//배열 출력
for (size_t i{0}; i < 10; i++){
cout << *(create_arr + i) << endl;
}
delete [] my_arr;
return 0;
}
정수가 배열로 변경됬고,
리턴 값이 생성된 배열에 대한 주소입니다.
여기서 헷갈릴 수 있는 점은 '로컬 변수의 포인터는 반환하지 말라고 한 것 아닌가?' 입니다.
이 규칙의 이유는 로컬 변수의 데이터는 heap 영역이 아닌 stack memory에 생성되기 때문입니다.
그리고 이 영역은 함수의 호출로 생성되고 리턴으로 사라집니다.
하지만 힙 영역에 존재하는 데이터는 한번 생성되면 사라지지 않습니다.
즉, 함수 호출 이후에 함수 종료 이후에도 계속 접근할 수 있는 값인 것 입니다.
위의 함수에서 보면, create_arr 함수 내에서
*new_arr 포인터가 선언되고 리턴되었습니다.
이 포인터가 가리키는 배열은 함수 영역에서 생겨나지 않고 힙 영역에서 생겼기 때문에,
이를 반환해도 문제가 없는 것 입니다.
왜 힙 영역에서 생긴건지는 동적 메모리 할당에 관련된 포스트를 읽으면 이해하실 수 있습니다.
그렇다면 잘못된 예시들은 어떤것일까요?
int *wrong_func(){
int size {};
...
return &size;
}
int *wrong_func2(){
int size{};
int *size_ptr {&size};
...
return size_ptr;
}
함수 내에서 선언된 변수 size에 대해서
그 값 자체 혹은 그 값에 대한 포인터를 반환하는 것은 잘못되었습니다.
왜냐면 그 값이 스택 영역에서 생성되었다가
함수 호출 종료 이후에는 사라질 값이기 때문입니다.
이런 문제는 당장 가시적인 오류를 발생시키지 않을 수도 있지만,
언젠가는 치명적인 오류를 발생시킬 수 밖에 없습니다.
이러한 개념들을 합친 예시 코드입니다.
#include <iostream>
using namespace std;
int *create_arrary(size_t size, int init_val = 0) {
int *new_storage = new int[size];
for (size_t i{0}; i < size; i++) {
new_storage[i] = init_val;
}
return new_storage;
}
void display_array(const int *const array, size_t size) {
for (size_t i{}; i < size; i++) {
cout << array[i] << " ";
}
}
int main() {
int *my_array = create_arrary(5, 100);
display_array(my_array, 5);
delete[] my_array;
cout << endl;
return 0;
}
'C++ > 함수 (Function)' 카테고리의 다른 글
[C++] transform (0) | 2024.01.05 |
---|---|
[C++] c_str() 함수 (0) | 2023.12.23 |
[C++] 재귀 함수 (Recursive Function) (0) | 2023.12.18 |
[C++] 참조로 전달하기 (Pass by Reference) (1) | 2023.12.17 |
[C++] 함수에 배열을 매개변수로 사용할 때 (Passing Arrays To Functions) (3) | 2023.12.17 |