낌새만 보이면 const를 들이대자!


-> 어떤 값이 불변이어야 한다는 제작자의 의도를 컴파일러 및 다른 프로그래머와 나눌 수 있는 수단.


1. const는 전역 혹은 네임스페이스 유효범위 내의 상수를 선언하는 데 사용할 수 있다.

--> const int Width = 10;


2. 파일, 함수, 블록 유효범위에서 static으로 선언한 변수에도 사용할 수 있다.

--> void SetX(){

static const int count = 1;

}


3. 클래스 내부의 데이터 멤버

-->  class AAA{

private:

const int count;

static const int Size = 10;   --> 객체 내부의 정적 멤버도 당연 적용할 수 있다.

}


4. 포인터

1. const int* aptr;                 --> 포인터로 데이터 조작을 하지 않겠다. 가리키는 대상을 상수화 --> 가리키는 대상은 바꿀 수 있음.

2. int* const aptr;                --> 하나만 가리키겠다. 포인터를 상수화 --> 데이터 조작은 가능

3. const int* const aptr;      --> 가리키는 대상도 바꾸지 못할 뿐더러, 포인터를 통한 데이터 조작까지 허용하지 않겠다.


5. STL의 반복자

STL의 반복자 즉 iterator는 포인터를 본뜬 것이기 때문에, 기본 동작원리가 T* 포인터와 흡사하다.

반복자를 const로 선언하는 것은 T* const 와 같다. --> 즉 포인터를 상수화 하겠다는 말이다.

그렇다면 가리키는 대상을 상수화 하려면 어떻게 해야 할까? --> const_iterator를 쓰면 const T* 와 같이 동작한다.

아래 예제를 보자.


vector<int> vec;


1. const vector<int>::iterator iter = vec.begin();          --> iter는 T* const 처럼 동작. 즉 위의 2번과 같이 포인터를 상수화한 형태

*iter = 10;                                                               -->  따라서 데이터 조작은 가능하다.

++iter;                                                                    --> 하지만 가리키는 대상을 바꾸는 것은 불가능!


2. vector<int>::const_iterator cIter = vec.begin();        --> cIter는 const T* 처럼 동작. 즉 위의 1번과 같이 가리키는 대상을 상수화한 형태

*cIter = 10;                                                             --> 따라서 데이터 조작이 불가능하다.

++cIter;                                                                  --> 가리키는 대상을 바꾸는 것은 가능하다!


6. 함수

ex)

const AAA operator(const AAA& lhs, const AAA& rhs);

AAA a, b, c;

1.   (a*b) = c;  

2.   if(a*b = c)  

---> 1,2번과 같은어처구니 없는 코드를 예방할 수 있다.


상수 멤버 함수


1. 이 함수를 통해서 멤버 변수의 값이 변경되는 것을 허용하지 않겠다!!

2. 상수화된 함수는 상수화되지 않은 함수의 호출을 허용하지 않는다.          --> 상수화 되지 않은 함수 내에서 데이터 조작의 가능성이 있기 때문

3. 또한 멤버 변수의 포인터를 리턴하는 것도 허용하지 않는다.                    --> 반환된 포인터로 조작의 가능성이 있기 때문

--> 따라서 const int* GetPtr () const  --> 이런 형식으로 진행하도록 하자.  4항목의 2번 참고

4. const 키워드에 유무에 따라 함수 오버로딩이 가능하다.


//////////////////// 멤버 함수

void show() const;                    1번

void show();                              2번

//////////////////// 객체 선언

AAA aaa;                

const AAA bbb;     


aaa. show();    --> 비상수 객체 --> 두 개의 show()를 모두 불러올 수 있다. -->우선순위가 높은 비상수 함수를 불러온다. 2번

bbb.show();    --> 상수 객체  --> 오직 상수 함수만을 불러올 수 있다. 1번


5. 클래스의 인터페이스 향상 --> 멤버 변수를 조작할 수 있는 함수는 무엇이고, 조작할 수 없는 함수는 무엇인가? 를 알아야한다.

6. 상수 객체를 사용할 수 있게 된다. --> 객체 전달을 상수 객체에 대한 참조자로 진행하는 것 --> 복사손실 복사비용을 없애주어 코드 효율 UP


7. 상수 객체

1. 상수 멤버 함수만 불러올 수 있다.


실제 프로그래밍에서 상수 객체가 생기는 경우

1. 상수 객체에 대한 포인터 혹은

2.상수 객체에 대한 참조자로 객체가 전달될 때이다.  (위의 6번 참고)


void print (const Player& cp){ ... }  


참고)

const int& GetInt(int& a) { return a; };      1번

int & GetInt(int& a) { return a; }               2번


1번의 경우

int a = 10;

int b = GetInt(a);   --> 가능

int &b = GetInt(a)  ---> 불가능. 데이터 조작의 위험성이 있다. 반환된 레퍼런스로 어떠한 데이터 조작도 할 수 없다.


2번의 경우 모두 가능.


Player& 리턴과

Player 리턴의 차이

--> 함수의 반환 타입이 객체의 참조형식일 경우 리턴된 객체가 그 자리에 반환되게 된다.

--> 참조형식이 아닐 경우 리턴된 객체의 복사본이 오게 된다.



const 키워드는 프로그램을 안정적으로 작성하는데 많은 도움을 준다.

기능적인 측면 말고도 오류를 쉽게 찾아낼 수 있다는 이점까지 줄 수 있다.

따라서 const 키워드는 가급적이면 많이 사용하도록 하자.


const에 대해 상당히 많은 내용이 정리되어 있다.

나름 쉽게 풀어쓴다고 썼지만 포스팅이 아직 어색하여

보기 썩 좋은 모양새는 아닌 듯 하다.


비트수준 상수성, 물리적 상수성 그리고 상수 비상수 멤버의

코드 중복현상을 피하는 방법에 대해서는 다음에 포스팅 하도록 하겠다.

+ Recent posts