정체불명의 모모

[Effective C++] Const에 대해 알아보자 본문

프로그래밍(c++)

[Effective C++] Const에 대해 알아보자

정체불명의 모모 2021. 10. 26. 15:25

안녕하세요.

이번에는 'effective c++'책에

있는 'const'내용에 대해 정리해 볼 겁니다.

'const'는 제가 알고 있는 이상으로 많은 역할을 한다는것을

책을 보고 알았네요.

역시...공부가 답이다.

여러분들도... ㅡㅜ 복붙이 아닌 공부를 하길...

그럼, 시작하겠습니다!


낌새만 보이면 const를 들이대 보자!
: const의 많은 역할에 대해 알아보자!

ㅁ const 의미 : const는 '의미적인 제약'을 주며(변경이 안되는), 컴파일러가 이 제약을 지켜준다는 것 입니다.

    어떤 값을 불변이어야 한다는 제작자의 의도를 컴파일러 및 다른 프그래머와 나눌 수 있는 키워드 입니다.

 

  1. 클래스 밖에서 const의 사용 방법
    - 전역 혹은 네임스페이스 유효범위의 상수를 선언합니다.
    - 파일, 함수 , 블록 유효범위 에서 static으로 선언한 객체에도 const를 붙일 수 있습니다.

  2. 클래스 내부에서 const의 사용 방법
    - 정적 멤버 및 비정적 데이터 멤버 모두를 상수로 선언 할 수 있다.

  3. 포인터에서 const의 사용 방법
    - 포인터 자체를 상수로 할 수 있다.
    - 포인터가 가리키는 데이터를 상수로 지정할 수 있다.
    char greeting[] = "Hello";  // 비상수 포인터
    char * p = greeting; 	// 비상수 데이터
    
    const char *p = greeting;   // 비상수 포인터, 상수 데이터
    
    char * const p = greeting;  // 상수 포인터, 비상수 데이터
    
    const char * const p = greeting;   // 상수 포인터, 상수 데이터​
     
     const 키워드가 *표의 왼쪽에 있으면 포인터가 가리키는 대상이 상수인 반면,
     const가 *표의 오른쪽에 있는 경우엔 포인터 자체가 상수 입니다.
     const 가 * 표의 양쪽에 다 있으면 포인터가 가리키는 대상 및 포인터가 다 상수라는 뜻입니다.

    4. 반복자에서 const의 사용 방법

        STL 반복자는 포인터를 본뜬 것이기 때문에, 기본적인 동작 원리가 T* 포인터와 진짜 흡사합니다.

           반복자는 자신이 가리키는 대상이 아닌 것을 가리키는 경우가 허용되지 않지만, 반복자가 가리키는 대상 자체는 

          변경이 가능합니다.

 

          - 반복자를 const로 선언하면 포인터를 상수로 선언하는 것 과 같습니다.

          - 변경이 불가능한 객체를 가리키는 반복자를 원하면 const_iterator를 이용하면 됩니다.

std::vector<int> vec;
// iter는 T* const 처럼 동작 합나디ㅏ.
const std::vector<int>::iterator iter = vec.begin();

*iter = 10;  // 가르키는 대상의 데이터는 변경이 가능 하지만,
++iter;  // Error! 가르키는 대상을 변경할 수 없습니다.

// cIter는 const T* 처럼 동작합니다.
std::vector<int>::const_iterator cIter = vec.begin();

*cIter = 10;   // Error!가르키는 대상의 데이터를 변경 할 수 없습니다.
++cIter;   	// 대상은 변경할 수 있습니다.

 

  5. 함수 선언에서의 const 의 사용 방법

     - const 는 함수 반환 값, 각각의 매개변수, 멤버 함수 앞에 붙을 수 있고, 함수 전체에 대해 const의 성질을 붙일 수 있습니다.

     - 함수 반환 값을 상수로 정해 주면, 안전성이나 효울을 포기하지 않고도 사용자 측의 에러 돌발 상황을 줄이는 효과를 가져다 줍니다.

 

  6. const 매개변수

      - 매개변수 혹은 지역 객체를 수정할 수 없게 하는것을 목적으로 선언 합니다.

 

  7. 멤버 함수에 const 역할

      - 해당 멤버 함수가 상수 객채에 대해 소출될 함수이다 라는 사실을 알려주는 것 입니다.
          1. 클래스의 인터페이스를 이해하기 좋게 하기 위해서

             : 클래스로 만들어진 객체를 변결할 수 있는 함수는 무엇이고, 또 변경할 수 없는 함수는 무엇인가를 사용자 쪽에서 알고 있어야

               하는 것입니다. 

                

          2. 상수 객체를 사용할 수 있게 하자는 것입니다.
              : 코드의 효율을 위해 아주 중요한 부분이기도 합니다.

                 객체 전달을 '상수 객체에 대한 참조자'로 진행하는 것이기 때문입니다. 

                 위 내용이 제대로 할 수 있기 위해선 상수 상태로 전달된 객체를 조작할 수 있는 const 멤버 함수, 즉 상수 멤버 함수가 준비

                 되어야 한다는 것이 포인트 입니다. 

 

                  ※ const 키워드가 있고 없고의 차이만 있는 멤버 함수들은 오버로딩이 가능합니다.


 ㅁ 어떤 멤버 함수가 상수 멤버라는 것이 어떤 의미 일까요??

  

1.  비트수준 상수성(물리적 상수성)

 : 비트 수준 상수성은 어떤 멤버 함수가 그 객체의 어떤 데이터 멤버도 건드리지 않아야 그 멤버 함수가 'const'임을 인정하는 개념입니다.

     즉, 그 객체를 구성하는 비트들 중 어떤 것도 바꾸면 안된다는 것 입니다.

   비트 수준 상수성을 사용하면 상수성 위반을 발견하는데 힘이 많이 들지 않습니다.

   c++에서 정의하고 있는 상수성이 비트 수준 상수성입니다.

   그리고 상수 멤버 함수는 그 함수가 호출된 객체의 어떤 비정적 멤버도 수정할 수 없게 되어 있습니다.

 

 

2. 논리적 상수성 

: 상수 멤버 함수라고 해서 객체의 한비트도 수정할 수 없는 것이 아니라 일부 몇 비트 정도는 바꿀 수 있되, 그것을 사용자측에서

  알아채지 못하게만 하면 상수 멤버 자격이 있다는 것입니다.

 


! 이것만은 잊지 말자 !

* const를 붙여 선언하면 컴파일러가 사용상의 에러를 잡아내는 데 도움을 줍니다.
  const는 어떤 유효범위에 있는 객체에도 붙을 수 있으며, 함수 매개변수 및 반환 타입에도 붙을 수 있으며, 멤버 함수에도 붙을 
   수 있습니다.
* 컴파일러 쪽에서 보면 비트 수준 상수성을 지켜야 하지만, 개념ㅈ먹인 상수성을 사용해서 프로그래밍 해야 합니다.
* 상수 멤버 및 비상수 멤버 함수가 기능적으로 서로 똑같게 구현되어 있을 경우에는 코드 중복을 피하는 것이 좋은데, 이때 비상수
  버전을 호출하도록 만드세요.

 

 

 

Comments