티스토리 뷰

const는 변수를 상수화 시키는 키워드이다.

상수란?

상수란 변하지 않는 값을 뜻한다.

변수란 한 번 선언하면 값을 계속 바꿀 수 있지만,
상수는 처음 선언할 때만 값을 할당할 수 있으며 그다음부터는 값을 바꿀 수 없다.

상수와 리터럴의 구분


리터럴은 "문자 그대로"라는 뜻인데 C/C++에서는 "값 그 자체"를 뜻한다.
상수는 변수처럼 리터럴이 저장된 공간이다.

상수를 왜 쓰나?

프로그램을 작성할 때 고정되어 있어야 할 값을 변수에 저장해서 사용하다 보면 실수로 값을 바꿀 가능성이 있다.
상수는 값을 바꾸는 것을 방지하기 위해 사용하며, 코드의 의도를 명확하게 만들 수 있다.


const의 기본 사용 예시

const int num = 1;
num = 2; // 상수에 값을 할당하였기 때문에 컴파일 에러 발생

const 변수의 위치

아래 코드는 동일한 기능을 한다. 즉, 위치는 상관이 없다.

const int num = 1;
int const num = 1;

 


const 멤버 변수

const 변수는 반드시 선언 시 초기화를 해야 한다. 즉, 초기화하지 않으면 컴파일 에러가 발생한다.
따라서 class나 struct의 멤버 변수를 const로 선언 시에는 반드시 초기화 리스트(initialize list)를 사용해야 한다.

class ConstExample
{
	const int num;
	
	ConstExample(void) : num(3); // 정상
};
class ConstExample
{
	const int num;
	ConstExample(void)
	{
		num = 3; // Compile Error
	}
};




const 포인터 변수

const 포인터 변수는, 일반 const 변수와 달리 const의 위치에 따라 의미가 달라진다.


1. 맨 앞에 위치할 때

const int * ptr = & num;

*ptr = 3; // compiler error
num = 3; // 정상

이는 포인터 변수가 가리키는 값을 상수화 시키는 것이다.
즉, *ptr의 값을 바꾸는 건 불가능하고, num을 바꾸는 건 가능하다.

2. 중간에 있는 경우

int num1 = 1;
int num2 = 2;
int* const ptr = &num1;

*ptr = 3; // 정상
ptr = &num2 // Compiler Error

포인터 변수 자체를 상수화 시킨다.
포인터 변수란 대상의 주소 값을 지정하는 변수이다. 위의 ptr은 ptr자체를 상수화 시키는 것이기 때문에, ptr의 주소 값을 바꾸는 것은 불가능하다.

3. 위 두 가지를 모두 사용한다면?

int num1 = 1;
int num2 = 2;
const int* const ptr = &num1;

*ptr = 5 // Compile Error
ptr = &num2 // Compile Error




함수에서의 const 사용


1. 매개 변수 자료형에 사용될 경우

int Function(const int num1, const int num2)

함수의 파라미터를 함수 내에서 변경하면 안 될 때, 이런 식으로 사용한다.
파라미터 값을 읽기만 가능하고 변경이 불가능하다는 이야기다.

2. 함수 선언에 사용되는 const 멤버 함수

class ConstExample
{
	void print() const {...}; // const 멤버함수
};

const멤버 함수는 이 함수 내에서 멤버 변수 num1과 num2가 변경이 불가능하다는 뜻이다.
여기서 알아둬야 할 것은 const멤버 함수는 오버 로딩이 가능하다는 것이다.
즉, 보통 매개변수의 개수나 데이터 타입 등으로 구분하는 오버 로딩 방식처럼, const의 유무로 오버 로딩이 가능하다.

class ConstExample
{
	void print() const { cout << " const print " << endl; };
	void print() const { cout << " normal print " << endl; };
};

그렇다면 함수 호출할 때 어떻게 구분이 될까?

int main()
{
	ConstExample object1;
	object1.print(); // 실행결과 : normal print 
}

const print함수는 const 선언한 객체에서 구분이 된다. 즉 아래와 같은 상황에서 구분이 될 수 있다.

int main()
{
	ConstExample object1;
 	const ConstExample object2;
 	object1.print(); // 실행결과 : normal print
 	object2.print(); // 실행결과 : const print
}

3. 함수 맨 앞, 리턴 자료형에 사용하는 const

함수 맨 앞에 리턴 자료형에 있는 const는 말 그대로 리턴 값을 상수화 한다는 것이다.

const int Function()
{
	return 10;
}

이 함수를 사용하려면 어떻게 해야 할까? const 키워드를 붙여서 받아야 할까?

const int Function()
{
	return 10;
}

int main()
{
	int num1 = Function();
	const int num2 = Function();

	num1 = 30;
	num2 = 30; // compiler error
}

num2는 당연히 컴파일 에러가 날 것이고, num1은? 문제가 있을 것 같지만 에러가 나지 않는다.
즉, 리턴 값을 상수화 시켜 보호하는 것이지 , 그걸 할당받아서 사용하는 num1의 값 변경까지 보호하진 않는다. 그렇다면 const를 쓰는 의미가 없지 않나?라는 생각이 든다.

맞다. 함수 리턴 타입에 const를 사용할 때는 레퍼런스를 붙여 사용할 때 의미가 있다.

const int& Function(int n)
{
	int& num1 = n; // 레퍼런스 임으로 리터럴 값을 할당할 수 없다.
	return num1;
}

int main()
{
	int& num2 = Function(); // error
	const int& num2 = Function(); // 정상
}

reference : https://dojang.io

 

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함