참조(reference)와 상수(const) 정리
C++공부 중 참조와 상수에서 이해가 힘들었던 내용을 적는다.
Base (건너 띄어도됨)
변수를 선언할 때 대강 아래와 같은 구조를 가지고있다.
[const/static ..] [자료형] [&/* ..] [변수명] = [임시변수에 들어간 상수 데이터]
이를 해석할 땐,
[임시변수에 들어간 상수 데이터] 를 [const/static ..] 으로 설정된 [자료형]을 가지는 [&/*](참조/포인터) 변수 [변수명]을 선언 한다.
이렇게 해석하면 된다.
이런식으로 작성한 이유가 해당 순서에 [변수명]을 [함수명]으로 바꾸고 뒤에 오는 내용을 매개변수로 바꾼다면,
[const/static ..] [(반환)자료형] [&/* ..] [함수명] ([매개변수]) { [코드] }
이처럼 함수로도 표현 할 수가 있다.
참조(Reference)
포인터와 비슷하면 다른 참조(Reference)형에 대해서 알아보자.
#include <iostream> int &RefRetFunc(int &num){ num++; return num } int main(){ int num1 = 1; int &num2 = RefRetFunc(num1); num2 += 10; std::cout << num1 << " " << num2 << std::endl; return 0; }
위 코드는
1. num1에 1을할당하고
2. &num2에 RefRetFunc()에서 받은 참조자를 할당해 넣고
3. num2 += 20을 한다
결과 값은
20 20
즉 &num2와 num1이 참조하는 대상이 같다는 것이다.
10번째 줄에서 &num2가 num2로 바꾸어보자.
#include <iostream> int &RefRetFunc(int &num){ num++; return num } int main(){ int num1 = 1; int num2 = RefRetFunc(num1); num2 += 10; std::cout << num1 << " " << num2 << std::endl; return 0; }
언듯 드는 생각으론 “함수가 반환하는 자료형은 (int &)인데 (int)형 자료에 넣을 수 있을까?”란, 생각이 드는데.
결론만 말하자면 들어간다. 다만 결과 값이 다르다.
2 12
즉, num2와 num1은 전혀 다른 대상이다.
++ Code 1와 같은 동작을 하는 코드를 Pointer로 만들어보자.
int *PtrRetFunc(int *num) { (*num)++; return num; } int main (){ int num1 = 1; int *num2 = PtrRetFunc(&num1); *num2 += 10; std::cout << num1 << " " << *num2 << std::endl; }
상수(Const)
이 포인터와 함께 쓰는것과 비슷하면서 좀 더 단순하다.
대부분의 경우는 생각하는데로 작동한다.
다만 몇가지 경우에 대해서 에러가 발생한다.
const int &RefRetFunc(int &num) { num++; return num; } int main() { int num1 = 1; int &num2 = RefRetFunc(num1); }
RefRetFunc는 “const” 형을 반환 하는데, 입력 받는 &num2는 “const”가 아니기에 에러가 발생한다.
하지만 int &num2 대신 int num2 를 사용하면 에러없이 작동 한다.
&num2는 num1과 같은 대상을 참조하지만 num2 전혀 다른 변수이기에 그런것이다.
즉 상수 참조자는 상수 참조자만 할당 할 수 있다는 뜻이다.
+++ 참조에 대한 추가 내용
int &test(){ int num = 1; return num; } int main(){ int &num = Test(); return 0; }
위와 같은 코드는 실행은 된다.
하지만 Test 함수 내부의 num을 참조하는 main의 num이 참조하는 곳을 Test 함수가 종료되면서 사라지게 되는데,
여전히 그곳을 참조하기에 에러가 발생 할 수 있다.