본문 바로가기

예전/C, C++

[C/C++] const 키워드



함수에 붙어있는 const



const int Func(const int* arr) const;


아 이게뭐야 하실지 모르겠지만 ... 저도 그러고있습니다. 이게뭐야!

const입니다.


const가 어디에 붙어있는가에 따라 함수의 특징이 달라지는데요, 하나씩 알아볼게요 !



1. void Func(const int& nNum);


첫 번째는 매개변수에 붙어있는 const 입니다.


그 전에 파라미터의 종류에 대해 알아보겠습니다.

파라미터는 사용 목적에 따라 in-parameter와 out-parameter로 나뉘는데요



in-parameter란,



함수에 nNum이라는 data를 전달하는 것이고,



out-parameter란,



함수에 의해 nNum이라는 data의 값이 바뀌는 것입니다.



정리하면 in-parameter 는 값전달, 주소전달, 레퍼런스 전달을 모두 할 수 있고,

 out-parameter는 주소전달, 레퍼런스 전달을 사용할 수 있습니다.




여기서 매개변수의 const가 나타납니다.


만약 in-parameter로 포인터 혹은 레퍼런스를 사용하고 싶은데, 값 변경의 위험이 느껴질 때 ! 

매개변수 앞에 const를 붙여 상수화 시키는 것입니다.



이렇게 하면 nNum의 값 변경을 시도하려고 할 때, 에러가 발생되 값변경을 불가능하게 합니다.




또한, class형식이 in-parameter 로 전달될때 복사 생성자가 호출되는 오버헤드를 줄이기 위해 보통 &를 붙입니다.




이때도 이 class 객체를 변경시키지 못하도록 const를 붙입니다.

우리의 목적은 그저 값을 사용하는 것이니까요.



결론은 간단합니다. in-parameter 로 쓰이는 포인터와 레퍼런스는 꼭 const를 쓸 것 !!^.^



2. void Func(void) const;


두 번째는 함수 선언에 사용되는 const 입니다.


이 함수 선언에 사용되는 const는 class 멤버함수에서만 사용됩니다.

왜냐하면 이 const의 목적이 const 멤버 함수 내에서 멤버 변수의 값 변경을 막는 것이기 때문이죠.





만약, const 멤버 함수에서 멤버 변수의 값을 변경하려 한다면 



이와같은 에러가 발생합니다.



const 객체들은 const 멤버 함수만 호출할 수 있습니다. 

왜냐하면 멤버 함수는 객체의 상태를 변경할 수 있는 권한을 가지고 있기 때문에, const 객체들이 호출 할 수 있는 함수는 const 멤버 함수 뿐 입니다.

비 const 객체들은 당연히 const 멤버 함수를 호출할 수 있습니다.


그런 이유로 멤버 함수의 기능이 객체의 상태를 변경하지 않는다면 const 멤버함수로 만들어야 합니다.



위 코드에서 볼 수 있듯 const 멤버 함수와 일반 함수는 오버로드가 가능하며 위의 결과는 아래와 같습니다.



비 const 객체는 일반 함수가 우선으로 호출되는 것을 볼 수 있습니다.




3.  const int& Func(void)


세번째는 리턴 자료형에 사용되는 const 입니다.




리턴 방식에는 여러가지가 있습니다.


값 리턴 방식, 레퍼런스 리턴 방식, 포인터 리턴 방식.

여기서 레퍼런스 리턴 방식과 포인터 리턴 방식은 참조 리턴 방식입니다.


참조 리턴 방식은 프로그래머가 의도한 방식이 아니기 때문에 클라이언트가 값을 변경하지 못하도록 해야 합니다.

따라서 const 를 붙여 상수화 시켜 값을 변경하지 못하게 합니다.




참조를 리턴할 때 복서 오버헤드를 줄이기 위해서 혹은 단지 필요에 의한 참조라면 꼭 const를 붙여야 합니다.

물론, 참조 리턴 방식을 피하는게 가장 좋은 방법입니다.




변수에 붙어있는 const



const int * const pNum;


네 또 알쏭달쏭한게 나왔네요 차근차근보면 어렵지 않을꺼예요 !! 


const int* pNum;

int* const pNum;

const int * const pNum;


뭐 이런게 많이 있습니다. 



여기서 자료형은 의미가 없으니 한번 지워볼게요!



이렇게 되었군요 ! 


1. const * pNum


만약 const 가 * 앞에 있으면 pNum은 *pNum이 됩니다.

따라서 포인터 pNum이 상수화 된 것이므로 값을 변경할 수 없습니다.



아래 예시를 봅시다.




위 코드에서 *pNum이 상수화 시켰기 때문에 

*pNum 의 값 변경이 불가능해졌습니다. 만약 값 변경을 시도한다면 아래와 같은 에러가 발생합니다.



하지만 *pNum만 상수화 시킨 것이기 때문에 pNum이 가리키는 대상은 변경할 수 있습니다.




2. * const pNum


이것은 pNum을 상수화 시킨 것입니다. 



이것은 pNum이 상수이므로 pNum이 가리키는 값은 변경할 수 있지만, 

pNum 자체는 변경할 수 없습니다.





생각보다 쉽지요?

문제시 댓글 달아주시면 수정해요 >,<



[참조]

http://blog.daum.net/coolprogramming/60

http://ra2kstar.tistory.com/143



'예전 > C, C++' 카테고리의 다른 글

[C/C++] 캡슐화와 은닉화  (2) 2012.10.29
[C/C++] 레퍼런스  (0) 2012.10.19
[C/C++] void*  (0) 2012.10.16
[C/C++] 변수 (지역, 전역, static, extern)  (0) 2012.10.16
[C/C++] malloc/free 와 new/delete  (0) 2012.10.15