DevNote

Effective C++ Item3:: const를 적극 활용! review 본문

C++/Effective

Effective C++ Item3:: const를 적극 활용! review

Ahnda 2020. 3. 12. 18:32

const

 - 의미적인 제약 :: const 키워드가 붙은 객체는 외부 변경을 불가능하게 한다.

 - 어떤 객체가 불변이어야 한다는 제작자의 의도를 컴파일러와 다른 개발자와 공유할 수 있는 수단


const의 특성

 - 상수를 선언(정의)하는데 쓸 수 있다.

 - static으로 선언한 객체에도 const를 붙일 수 있다.

 - 어떠한 객체에도 붙을 수 있다. (객체 변수, 함수 파라미터 및 리턴 값, 멤버 함수, 포인터)


포인터와  const

 - 포인터 자체를 상수로, 혹은 포인터가 가리키는 데이터를 상수로, 혹은 둘 다 상수로 지정할 수 있다.

 

다음의 내용은 아래의 예제를 통해 확인할 수 있다.

 

 - 포인터가 가리키는 대상을 상수로 만들 때  const를 사용하는 스타일은 조금씩 다르다. 타입 앞에 cosnt가 붙을 수도 있고, 타입의 뒤쪽이자 *표 앞에 const를 붙일 수도 있다. 

 

의미적인 차이는 전혀 없다. 아래의 함수를 통해 설명하자면, 

void f1(const CTest* p);	// f1은 상수 CTest 객체에 대한 포인터를 파라미터로 취한다
void f2(CTest const* p);	// f2도 마찬가지

두 함수의 const 위치는 다르지만 내용적인 측면에서는 차이가 전혀 없다.

위의 구문은 눈에 익혀두는 게 좋다.

 

다만 아래의 경우와 혼동되서는 안된다.

void f3(CTest * const p);

iterator와 const

 - 기본적으로 STL iterator의 동작원리는 T* 포인터와 비슷하다. 어떤 반복자를 const로 선언하는 것은 포인터를 상수로 선언하는 것과 같다.

T* const iter;

iterator는 자신이 가리키는 대상이 아닌 다른 것을 가리키는게 허용되지 않지만, 가리키는 대상 자체는 변경이 가능하다. 만약, 변경 불가능한 객체를 가리키는 iterator가 필요하다면 const_iterator를 쓴다.

 

아래의 예제는 const_iterator에 대한 것이다.

const T* iter;


함수와 const

 가장 실용도가 높은 const의 쓰임새는 바로 함수 선에 쓸 경우다. 함수를 선언함에 있어서 cosnt는 함수 리턴 값, 파라미터, 멤버 함수 앞에 붙을 수도 있고, 함수 전체에 const의 성질을 부여할 수도 있다.

 

** 함수 리턴 값을 const로 지정하면, 안전성이나 효율을 포기하지 않고도 사용자 측의 에러 동발 상황을 줄일 수 있다.

아래의 두 예제는 다음과 같은 상황을 보여준다.

class CTest2
{ ... };

const CTest2 operator*(const CTest& lValue, const CTest& rValue);

위의 예제를 보면 굳이 operator*의 리턴 값이 상수일 필요가 있는지 의문이 들 수 있다. 그런데 상수 객체로 되어 있지 않으면 사용자 쪽에서 아래와 같이 실수를 저지를 수 있다.

CTest2 a, b, c;

...

(a * b) = c;		// a*b의 결과에 operator=를 호출

두 수의 곱에 대입 연산을 취하고 싶은 개발자가 있을지는 모르겠지만, 이런 상황을 원하지 않았지만 무의식 중에 충분히 저지를 수 있는 실수이다. (bool로 implicit 형변환이 가능한 타입도 포함)

if(a * b = c) ...	// 단순 비교를 의도하였으나...

위의 예제는 a와 b의 타입이 기본제공 타입이었다면 명백히 신택스 에러를 일으키는 코드지만, 사용자 정의 타입들의 특징 중 하나는 기본제공 타입과의 쓸데없는 비호환성을 피한다는 것인데, 위에서 본 바와 같이 두 수의 곱에 대해 대입 연산이 되도록 놓아두는 것이 바로 '쓸 데 없는' 경우가 됐다.

 

이 때! operator*의 리턴 값을 const로 정해두면 이런 경우를 미연에 방지할 수 있다.

 

*** 어떤 객체나 변수든 수정할 수 없게 하는 것이 목적이라면 const로 선언하는 것을 잊지 말자!


const 멤버 함수

 멤버 함수에 const 키워드를 붙이면 다음과 같은 의미가 된다.

 " 이 멤버 함수가 const 객체에 대해 호출될 함수다. "

 

얼핏 보기에는 의미가 와닿지도 이걸 왜 써야하는지도 의문이 들 수 있다. 그렇지만 그러한 의문에 대해 시원하게 내놓을 수 있는 대답은 두 가지다.

 1) 클래스의 인터페이스를 쉽게 이해하도록 하기 위해서!

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

 

 2) const 키워드를 통해 상수 객체를 사용할 수 있게! (Item 20과 연관됨)

  :: C++프로그램의 실행 성능을 높이는 핵심 기법 중 하나가 객체 전달을 '상수 객체에 대한 참조자(reference-to-const)'로 진행하는 것이다.

=> 이 기법이 제대로 적용되려면, 상수 상태로 전달된 객체를 조작할 수 있는 const 멤버 함수가 준비되엉 있어야 한다는 것이 포인트이다.

'C++ > Effective' 카테고리의 다른 글

#define 대신 Inline  (0) 2020.03.11