CPP 초급 강좌 21. C++ reference return, rvalue reference &&
이전 글에서 call by value, call by reference 에 대하여 (함수인자 사용을 통해) 살펴본 적이 있는데요,
관련링크
이번에는 reference return 에 대해 보겠습니다.
return by value
아래 코드를 볼까요.
class Point
{
public:
float x = 0.0f;
float y = 0.0f;
};
Point p;
Point f1()
{
return p;
}
int main()
{
f1().x = 100;
}
가능할까요? 답은 불가합니다.
return by reference
좀 더 자세히 안 되는 이유를 설명하면, f1()의 리턴인 Point는 return by value 입니다. 리턴시 복사가 일어나 임시객체가 반환되는 상태입니다. 값을 수정할 수 없습니다.
위의 코드가 전역의 생성된 Point p;를 반환하려는 의도였다면, return by reference 로 접근해야 합니다.
Point& f1()
{
return p;
}
int main()
{
f1().x = 100;
cout << p.x << endl;
}
이와 같은 코드는 가능합니다.
정리하면
return by value 복사된 값을 넘겨줍니다. 리턴 값을 즉시 사용할 수 없습니다.
return by refererce 복사본인 아닌 실제값을 다른 이름, 그냥 실제 값이라고 생각하시면 편합니다.
용도에 맞게 사용하시면 됩니다.
primitive type
int n;
int& f1()
{
return n;
}
int main()
{
f1() = 100;
}
문제없는 코드
시스템이 제공해주는 primivie type(int,float,double...)등 또한 똑같이 작동됩니다.
지역변수 주의
int& f1()
{
int n1;
return n1;
}
이런 코드는 어떨까요? 지역변수를 선언하고 그 변수를 리턴합니다. return by reference 입니다.
컴파일러는 일단, warning C4172: 지역 변수 또는 임시: n1의 주소를 반환하고 있습니다. 을 주긴 하지만 프로그램 자체는 빌드도 되고 돌아갈 수 있습니다.
하지만 위의 코드는 정말 위험한 코드입니다.
n1은 기본적으로 지역변수입니다. 해당 함수에서 생명력을 다하게 되는데 그 값을 주소를 반환시키는 행위입니다. 컴파일러에 따라 해당 영역을 메모리를 바로 회수하거나 좀 더 그 시점이 뒤 일수 있는데요, 차라리 바로 회수되고 프로그램이 터지면 다행입니다. 이는 에러를 인지하고 바로 수정할 수 있으니까요.
가끔 회수 시점이 틀릴 수가 있습니다. 그리고 프로그램 사용자가 느끼기에 랜덤하다고 생각할 확률이 큽니다. 프로그램이 구동하나 어느 시점에서 죽을지 알 수가 없는 위험도가 있는 코드입니다. 큰 프로그램이라면 이런 오류는 정말로 대응하기 어렵습니다.
주의가 필요한 코드입니다.
rvalue reference
다음 코드를 보아요.
int n1 = 0, n2 = 0;
n1 = 0; //a
0 = n1; //b
n2 = n1; //c
a는 가능한 코드입니다.
b는 불가능한 코드입니다. 0은 우변에는 올 수 있지만 좌변에는 위치할 수 없습니다.
c는 가능한 코드입니다.
0과 같이 우변에만 올 수 있는 값들을 cpp에서는 rvalue 라고 합니다.
반대로 n1과 같이 우변에도, 좌변에도 올수 있는 경우 lvalue 라고 합니다.
레퍼런스에서는 어떨까요? 다음 코드를 봅시다.
int& r1 = n1; //d
int& r2 = 10; //e
d는 이미 많이 본 코드이며 가능한 코드입니다. e는 불가능한 코드입니다. 레퍼런스는 rvalue를 담을수 없습니다.
하지만 다음과 같은 코드는 또 가능합니다.
const int& r3 = n1; //f
const int& r4 = 10; //g
f, g 모두 가능한 코드입니다. const & 일 경우는 우변이 lvalue, rvalue 모두 담을수 있습니다.
c++11 부터 rvalue 만 담을 수 있는 reference 형식이 나왔습니다.
int&& r5 = n1; //h
int&& r6 = 10; //i
h는 불가합니다. i 코드만 가능합니다. && 는 rvalue reference는 rvalue만 담기 위한 문법입니다.
형식&& 요것이 등장하면서 기존에 형식& 만 존재할 때와 명칭이 조금 달라졌습니다.
이전에는(c++11) 레퍼런스라고 하면
형식&
현재(c++11) 이후는 아래 둘다 래퍼른스입니다.
형식& 더 정확한 명칭은 lvalue reference
형식&& 더 정확한 명칭은 rvalue reference
뭐여? 이런건 왜 있는 거여 라고 하여 사용 용도를 보여드리고 싶은데, 요게 사용되는 부분이,
move semantics, perfect forwarding 등 난이도가 있는 주제라서, 지금은 그냥 아 이런 기능이 있구나 정도로 보고 넘어가시는 게 좋을 거 같습니다.
'IT > C++(CPP)' 카테고리의 다른 글
CPP 초급 강좌 23. C++ 동적메모리 사용(new, delete, delete[]), nullptr (6) | 2020.11.02 |
---|---|
CPP 초급 강좌 22. C++ Explict type conversion(casting) (6) | 2020.11.01 |
CPP 초급 강좌 20. C++ const reference (16) | 2020.10.30 |
CPP 초급 강좌 19. C++ 레퍼런스 reference (6) | 2020.10.29 |
CPP 초급 강좌 18. C++ if init, if constexpr, rang for (4) | 2020.10.28 |
댓글