본문 바로가기
C & C++/윤성우의 열혈 C++ 프로그래밍

[열혈 C++] const의 의미와 참조자

by 거북이 코딩 2023. 12. 19.

const의 의미

 

const int num=10;   

->    변수 num을 상수화

 

const int * ptr1=&val1;

->    포인터 ptr1을 이용해서 val1의 값을 변경할 수 없음

 

int * const ptr2=&val2;

->    포인터 ptr2가 상수화 됨

 

const int * const ptr3=&val3;

->    포인터 ptr3가 상수화 되었으며, ptr3를 이용해서 val3의 값을 변경할 수 없음

 

참조자

 

 참조자란 어떤 변수에 추가적으로 이름을 붙여주는것으로, 기존의 변수명과 같은 메모리 공간을 사용한다. 참조자의 선언은 자료형 뒤에 '&'를 붙여 선언한다. 선언 형태 : 자료형& 참조자명=변수;

int num1=20;     //변수 num1에 20을 저장
int& ref=num1;   //ref라는 참조자로 num1을 참조

 

 예를 들면 위와 같은 형태로 이미 있는 변수 num1에 ref라는 이름을 추가로 붙여주는것이다. 참조자는 변수처럼 연산이 가능하고 기존 참조자를 대상으로 새로운 참조자를 선언할 수 도있다. 포인터 변수도 변수이기 때문에 참조자를 선언할 수 있다.

int num = 20;
int* ptr = #
int** dptr = &ptr;

int ref = num;
int *(&pref) = ptr;
int **(&dpref) = dptr;

 

 포인터를 대상으로 참조자를 선언하면 위와 같은 형태가 된다.

 

참조자와 함수

 

 참조자를 사용하면 함수에서 메모리 공간에 접근하여 값을 바꿀 수 있다. 우선 코드를 보자.

#include <iostream>

using namespace std;

void AddOne(int& ref);

int main(void) {
	int num = 20;
	AddOne(num);
	cout << num;
	return 0;
}

void AddOne(int& ref) {
	ref++;
}
21

 

 위 코드를 보면 AddOne 함수의 매개변수로 참조자를 선언하고있다. 함수를 호출하게 되면 int& ref=num;이 선언된다. 함수 내에서의 ref가 함수 밖의 num과 같은 메모리공간을 사용하고 있는것이다. 때문에 함수 내에서의 ref++이 num에 영향을 주고 있다. 이를 응용하면 참조자를 이용해 포인터 변수가 가르키는 대상을 서로 바꿔주는 함수도 가능하다.

#include <iostream>

using namespace std;

void SwapPointer(int*& ptr1, int*& ptr2);

int main(void) {
	int num1 = 10, num2 = 20;
	int* ptr1 = &num1, * ptr2 = &num2;
	cout << ptr1 << endl << ptr2 << endl<<endl;
	SwapPointer(ptr1, ptr2);
	cout << ptr1 << endl << ptr2 << endl;
	return 0;
}

void SwapPointer(int* (&ptr1), int* (&ptr2)) {
	int* ptr = ptr1;
	ptr1 = ptr2;
	ptr2 = ptr;
}
0000000896BDFCA4
0000000896BDFCC4

0000000896BDFCC4
0000000896BDFCA4

 

 실행결과를 보면 포인터 가르키던 주소값이 서로 바뀌었음을 볼 수 있다. SwapPointer 함수를 선언하게 되면 전과 같이 int* (&ptr1)=ptr1, int* (&ptr2)=ptr2; 가 선언된다. 함수내의 포인터들이 함수밖의 포인터들과 같은 메모리 공간을 사용하게 되는것이다.

 

반환형이 참조자인 함수

 

 함수의 반환형으로 참조자를 사용할 수 도있다. 참조자를 반환하게 되면 반환과 동시에 다른 참조자에 참조될 수 있다.

#include <iostream>

using namespace std;

int& ReturnRef(int& ref);

int main(void) {
	int num = 10;
	int& refnum = ReturnRef(num);    //함수내에서 num 1증가
	refnum++;    //num을 참조한 refnum을 통해 num 1증가
	cout << num;    //num=12
	return 0;
}

int& ReturnRef(int& ref) {
	ref++;
	return ref;
}
12

 

 위와 같은 형태로 함수를 선언할때의 주의점은 함수의 지역변수를 참조의 형태로 반환하면 안된다는 것이다. 함수 안에서 선언된 변수를 함수 밖의 참조자가 참조하게 되면 함수의 종료와 함께 참조의 대상이 소멸하기 때문이다.

 

const 참조자

 

 참조자는 보통 변수만 참조할 수 있다. 하지만 const를 붙여주게 되면 상수를 참조하는것도 가능하다. const 참조자가 상수를 참조하게 되면 상수를 임시변수로 할당하여 참조하게 된다. 상수를 참조할 수 있게 되면 참조자를 매개변수로 갖는 함수에서 상수도 받을 수 있게 된다.

#include <iostream>

using namespace std;

int Adder(const int& num1, const int& num2);

int main(void) {
	int num1 = 10, num2 = 20;
	cout << Adder(num1, num2) << endl << Adder(10, 20);
	return 0;
}

int Adder(const int& num1, const int& num2) {
	return num1 + num2;
}
30
30