*개인적인 공부 내용을 기록하는 용도로 작성한 글 이기에 잘못된 내용을 포함하고 있을 수 있습니다.
#1 Return By Value
#2 Return By Address / Reference
#1 Return By Value
getValue 함수는 값(Value)을 반환하는 간단한 Return-By-Value 함수입니다. Return-By-Value 함수는 복사 과정이 많이 일어나서 비효율적이라는 단점이 있습니다. 물론 아래 코드처럼 간단한 케이스는 상관 없지만 배열이나 구조체 등 데이터가 많은 자료형을 반환할 때는 문제가 발생할 수 있습니다.
#include <iostream>
using namespace std;
// return by value
int getValue(int x)
{
int value = x * 2;
return value;
}
int main(){
int value = getValue(3);
return 0;
}
#2 Return By Address / Reference
다음으로 함수의 반환값으로 포인터 즉, 주소를 반환하는 케이스입니다.
#include <iostream>
using namespace std;
// return by address
int* getAddress(int x)
{
int value = x * 2;
return &value;
}
getAddress 함수의 리턴값을 받는 방법은 2가지를 떠올릴 수 있습니다. 첫 번째는 *(de-referencing) 연산자를 이용해 리턴값을 받는 방법입니다.
int main(){
int value = *getAddress(5);
return 0;
}
하지만 이 방식은 위험한 생각입니다. 왜냐하면 getAddress 함수의 지역변수 value는 getAddress 함수가 종료되면 메모리가 사라지기 때문입니다. 이처럼 사라질 변수를 de-referencing 하는 것은 큰 위험이 있습니다.
실제로 value에 들어있는 값을 출력해 보면 가비지 값(예상치 못한 쓰레기값)이 출력됩니다.
#include <iostream>
using namespace std;
// return by address
int* getAddress(int x)
{
int value = x * 2;
return &value;
}
int main(){
int value = *getAddress(5); // 사라질 변수를 de-referecing 하는 것은 위험이 있음.
cout << value << endl;
return 0;
}
-831371064
혹은 포인터 변수를 이용해 변수의 주소값을 받는 방법을 떠올릴 수 도 있습니다. 하지만 이 방식은 더 위험합니다.
사라질 변수(getAddress의 value)의 주소값을 담고 있는 상황이 되어 버리기 때문입니다.
#include <iostream>
using namespace std;
// return by address
int* getAddress(int x)
{
int value = x * 2;
return &value;
}
int main(){
int *value = getAddress(5);
return 0;
}
참조자(&)의 경우도 마찬가지입니다. 아래처럼 코드를 작성하면 가비지값으로 초기화될 수 있습니다.
//return by refference
int& getRef(int x)
{
int value = x * 2;
return value;
}
int main(){
int value = getValue3(5);
int &value = getValue3(5);
return 0;
}
이처럼 리턴값이 임시적으로 생겼다가 사라지는 지역변수인 경우 위에 소개한 방식처럼 리턴하는 것은 예상치 못한 결과를 불러 일으킬 수 있습니다.
단, 아래처럼 메모리가 함수의 실행 여부에 영향을 받지 않고, 확실하게 잡혀있는 상태라면 참조자만을 보내는 것은 괜찮습니다.
int& get(std::array<int, 100>& my_array, int ix)
{
return my_array[ix];
}
int main(){
std::array<int, 100> my_array;
get(my_array, 30) = 30;
return 0;
}
* 정리
1. Return By Value 방식은 간편하지만 복사가 많이 일어나 비효율적이라는 단점이 있다. 작은 크기의 데이터를 리턴하는 것은 문제가 되지 않지만 다수의 데이터를 갖고 있는 배열이나 구조체 같은 자료형을 리턴 시에는 문제가 될 수 있다.
2. Return By Address/Reference 방식의 함수에서 리턴값이 임시적으로 생겼다가 사라지는 지역변수인 경우 예상치 못한 결과를 불러 일으킬 수 있다. 단, 메모리가 함수의 실행 여부에 영향을 받지 않고 확실하게 잡혀 있는 상태에서 주소값/참조자를 보내는 것은 괜찮다.
'Archive2 > C&C++' 카테고리의 다른 글
[C++] #1 클래스 (Class) (0) | 2022.02.22 |
---|---|
[C/C++] VOL1 함수 포인터 (Function Pointer) 개요 (0) | 2022.02.10 |
[C/C++] const int& vs const int (0) | 2022.02.06 |
[C/C++] Call-By-Value VS Call-By-Reference (0) | 2022.02.06 |
[C++] 문자열 기호적 상수 (char[] vs char* vs const char*) (0) | 2022.02.02 |