[ Effective C++ ] 항목 3 : 낌새만 보이면 const를 들이대 보자!

Minsu._.Lighting·2023년 11월 13일
0

[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "

[핵심]

" const는 팔방미인! "

  • const를 붙여 선언하면 컴파일러가 사용상의 에러를 잡아내는 데 도움을 준다!
  • 컴파일러는 비트수준 상수성을, 프로그래머는 논리적 상수성을 생각하자!
  • 상수,비상수 멤버 함수가 기능적으로 똑같게 구현될 경우 비상수 버전이 상수 버전을 호출하도록 만들어 코드 중복을 피하자!

💡 const란 무엇인가!

  • 객체의 외부 변경을 불가능하게 해주는 키워드.
    소스코드 수준에서 붙이기 때문에 제작자의 의도를 컴파일러와 다른 프로그래머에게 알려줄 수 있다!

📌 클래스 외부에서의 const

[ 상수 선언 ]

  • 전역, 네임스페이스 유효 범위의 상수 선언(정의)에 쓰임!

  • 파일, 함수, 코드 블록 유효 범위에서 정적(static)으로 선언한 객체도 const 사용 가능!

📌 클래스 내부에서의 const

  • 정적, 비정적 데이터 멤버 모두 상수로 선언 가능!

  • 포인터와 const

    • [ 비상수 포인터, 비상수 데이터 ]
      char* p = "Smile";

    • [ 비상수 포인터, 상수 데이터 ]
      const char* p = "Smile";

    • [ 상수 포인터, 비상수 데이터 ]
      char* const p = "Smile";

    • [ 상수 포인터, 상수 데이터 ]
      const char* const p = "Smile";


      📢 *를 기준으로 좌측에 위치하면 가리키는 대상이 '상수'
      📢 *를 기준으로 우측에 위치하면 포인터 자체가 '상수'
      📢 가리키는 대상을 상수로 만들 때 const의 위치는 두 가지 방법이 있으며 두 방법 모두 자주 쓰인다!
      const int* pNum;
      int* const pNum;

📌 STL 반복자(iterator)와 const

  • 반복자는 포인터를 본떠 만든 것이기에 동작원리가 같다.
    => 반복자를 const로 선언하는 것은 상수 포인터와 같다.

  • 반복자가 가리키는 대상을 변경시키지 못하게 하려면 const_iterator를 사용!

[예시 코드]
vector<int> vec;

const vector<int>::iterator iter = vec.begin();

*iter = 10;				// OK, 가리키는 대상 변경 가능!
++iter;					// 에러! iter는 상수!

///////////////////////////////////////////////////////////////////////////

vector<int>::const_iterator citer = vec.begin();

*citer = 10; 			// 에러!, *citer는 상수!
++citer;				// OK, citer는 변경 가능!

📌 함수와 const

  • 반환 값에 const
    안전성, 효율성을 포기하지 않고도 에러를 줄일 수 있다!

    [ 예시 #1 ]
    ( a * b ) = c
    => ( a * b )의 return값을 const로 했으면 변경이 불가능 해 컴파일 오류가 발생해 이상 동작 방지 가능!


    [ 예시 #2 ]
    if(a + b = c)
    => bool로 암시적 변환이 가능한 경우에서의 오류

  • 매개변수에 const
    매개변수 혹은 지역객체를 수정할 수 없게 하는 것이 목적이라면 꼭 const를 붙이자!

  • 멤버함수에 const
    - 해당함수가 상수객체에 대해 호출될 함수임을 알려줌!
    - 클래스의 인터페이스를 이해하기 쉽게 만들어 줌!
    - 상수객체를 사용할 수 있으므로 상수 객체에 대한 참조자로 객체 전달을 할 수 있어 프로그램의 실행 성능을 높일 수 있음!
    - const의 유/무 차이만 있는 멤버 함수들은 오버로딩이 가능!


💡 멤버함수가 상수(const)멤버 라는 의미는?

📌 비트수준 상수성

" 객체의 어떤 데이터 멤버도 건드리지 않아야 const임을 인정 함"

  • C++에서 정의하고 있는 상수성

  • 상수성 검사가 쉬움
    함수 내부에서 데이터 멤버에 대해 대입 연산이 있는지만 검사하면 되기 때문

  • 하지만 비트수준 상수성 검사에 걸리지 않으면서도 데이터 멤버를 바꿀 수 있는 문제점이 나타남

    class CTextBlock
    {
    public:
    	char& operatorp[](size_t position) const
    	{
       		return pText[position];
    	}
       
       private:
       	char* pText;
    };
    .
    .
    .
    const CTextBlock cctb("Hello");				// 상수 객체 선언
    
    char* pc = &cctb[0];						// 상수 버전의 operator[]를 호출
    
    *pc = 'S';									// cctb는 "Sello"라는 값을 갖음

📌 논리적 상수성

" 데이터의 일부 정도는 바꿀 수 있되 사용자가 모르게만 해도 const임을 인정 함"

  • 비트수준 상수성을 보완하고자 등장

  • mutable 키워드를 사용


    💡 상수, 비상수 멤버함수 끼리 코드중복을 피하는 방법!

  • 비상수 버전 함수가 상수 버전의 함수를 호출하도록 함수를 정의하자!
    반대의 경우에는 수정하지 않겠다고 달아놓은 const 키워드가 무색해지는 행위!

profile
오코완~😤😤

1개의 댓글

comment-user-thumbnail
2023년 11월 18일

어머 저도 코딩 공부하는 학생이에요~ 같이 소통하며 공부해여╰(°▽°)╯

답글 달기

관련 채용 정보