#include <iosteam>
using namespace std;
int getValue(int x)
{
int value = x * 2;
//이 함수에서만 유효한 value가 선언이 되고 3 * 2를 연산하여 복사하여 대입된다.
return value;
}
int main()
{
int value = getValue(3);
//value가 선언이 되고 해당 함수의 리턴값이 복사하여 대입된다.
return 0;
}
안전하지만 복사와 변수의 생성등이 여러번 일어난다.
#include <iostream>
using namespace std;
int* getValue(int x)
{
int value = x * 2;
return &value;
}
int main()
{
int value = *getValue(3);
return 0;
}
반환형으로 값의 주소를 반환한다. 그 함수의 리턴값에 디레퍼런싱(dereferencing)한다.
당장 값(리터럴)을 다른 변수에 넣어서 쓰고자하면 쓸 수는 있지만
이 방법은 함수내에서 쓰이고 없어지는 value의 주소를 참조하는 것이기 때문에 좋은 방법은 아니다.
그리고 더 위험한 경우를 보자.
#include <iosteam>
using namespace std;
int* getValue(int x)
{
int value = x * 2;
return &value;
}
int main()
{
int *value = getValue(3);
return 0;
}
같은 함수이지만 차이점은 main함수 내에 있다. 해당 주소에 있는 값을 바로 디레퍼런싱하는 것이 아닌
변수에 그 주소를 담았다. 이를 사용하기 위해서 담는다면 운영체제가 메모리를 어떻게 쓸 지 모르기에
프로그래머입장에서는 위험한 변수일 수 있다.
#include <iostream>
int* allocateMemory(int size)
{
return new int[size];
}
int main()
{
int *array = allocateMemory(1024);
delete[] array;
//메모리할당은 함수에서 받고 함수 밖에서 메모리를 반납하고 있다.
return 0;
}
일반적으로는 할당과 반납이 다른 곳에서 이루어지므로 프로그래머입장에서는 힘들 수 있다.
#include <iostream>
using namespace std;
int& getValue(int x)
{
int value = x * 2;
return value;
}
int main()
{
int &value = getValue(5);
cout << value << endl;
cout << value << endl;
return 0;
}
10
3609371
함수의 반환값을 그대로 참조하고 있다. 출력문과 같이 10을 가지고 있다.
함수에서 반환된 뒤 쓰레기값이 들어간 상황이다.
#include <iostream>
using namespace std;
int& getValue(int x)
{
int value = x * 2;
return value;
}
int main()
{
int value = getValue(5);
cout << value << endl;
cout << value << endl;
return 0;
}
10
10
main 함수내의 value로 가져와서 출력하므로 비교적 안전하지만 이것 역시 좋은 방법은 아니다.
그렇다고 reference가 전혀 쓸 모가 없는 것은 아니다.
#include <iostream>
#include <array>
using namespace std;
int& get(std::array<int, 100>& my_array, int ix)
{
return my_array[ix];
}
int main()
{
std::array<int, 100> my_array;
my_array[30] = 10;
get(my_array, 30) = 1024;
cout << my_array[30] << endl;
return 0;
}
1024
이렇게 안전한 영역(메모리)에서 선언을 하고 그 값을 수정하는 함수는 따로 쓰는 경우가 많다.
위 코드에서는 배열의 인덱스의 참조를 반환하는 함수를 정의하여 해당 인덱스의 접근경로를 반환받아 사용한다.
이제 여러개의 자료형을 반환해보자.
그래픽스를 하다보면 C.style로 코딩해야할 수도 있는데 그럴때는 구조체를 많이 사용한다.
#include <iostream>
using namespace std;
struct S
{
int a, b, c, d;
};
S getStruct()
{
S my_s{ 1, 2, 3, 4 };
return my_s;
}
int main()
{
S my_s = getStruct();
cout << my_s.a << endl;
return 0;
}
또는 tuple을 사용할 수 있다.
#include <iostream>
#include <array>
#include <tuple>
using namespace std;
std::tuple<int, double> getTuple()
{
int a = 10;
double d = 3.14;
return std::make_tuple(a, d);
}
int main()
{
std::tuple<int, double> my_tp = getTuple();
cout << std::get<0>(my_tp) << endl; //a
cout << std::get<1>(my_tp) << endl; //b
}
튜플로 감싸서 반환하게 할 수도 있다.
c++17에서는 auto키워드로 자료형을 몰라도 크기에 맞추어 받게끔 할 수 있다.
'개발공부 > C++' 카테고리의 다른 글
키워드 : friend (0) | 2019.10.23 |
---|---|
정적 멤버 (0) | 2019.10.23 |
다중포인터와 동적 다차원 배열 (0) | 2019.10.22 |
포인터와 참조의 멤버 선택 (0) | 2019.10.22 |
참조변수 reference variable (0) | 2019.10.22 |