본문 바로가기
책 정리/Effective C++ 3rd

항목 2. #define을 쓰려거든 const, enum, inline을 떠올리자

by ocean20 2019. 12. 4.

1. #define ASPECT_RATIO 1.653의 결과는?

  (1) 결과 - 우리에겐 ASPECT_RATIO 보이지만, 컴파일러에겐 보이지 않음. 선행처리자가 컴파일러에게 넘기기전에 1.653으로 바꾸기 때문이다.

  (2) 예상문제점 - 컴파일러에서 문제가 생길시 1.653 문제가 있다고한다.(ASPECT_RATIO 아닌) 사용자는 1.653 어디서 왔는지 모를 있다. 또한 컴파일러에서 사용하는 데이터구조 테이블인 심볼테이블에 인풋되지 않는다.

 

 

2. 해결방법 - 매크로대신 상수를 사용하자.

const double AspectRatio = 1.653;

  (1) 장점 : 데이터를 줄일수있다, 심볼테이블에 인풋된다.

  (2) 이유 : ASPECT_RATIO 10번쓰면 10개의 사본이 생기기 때문이다.

 


3. #define대신 const 대체할때 주의사항

  (1) 상수포인터 정의시, 포인터와 가리키는값 둘다 const를 써주자 --> 항목3. 에서 다시 학습

//Const Pointer
int* const cpIntVal = &intVal1;

cpIntVal = &intVal2; // ERROR - 포인터가 상수이므로 주소 변경불가
cpIntval += 10;

//Pointer to const
const int* pcIntVal = &intVal1;

pcIntVal = &intVal2;
pcIntval += 10;	//ERROR - 포인터가 가리키는 값 변경 불가

//const Pointer to Constant
const int* const ccIntval = &intVal;

pcIntVal = &intVal2; // ERROR - 포인터가 상수이므로 주소 변경불가
pcIntval += 10;	//ERROR - 포인터가 가리키는 값 변경 불가

http://blog.naver.com/PostView.nhn?blogId=whwns0518&logNo=20185650637 (위 코드 참고)

 

  (2) 클래스 멤버로 상수를 정의하는 경우

class test{
private:
static const int numTurns = 5;
};

    1) 이때, numTurns의 사본을 한 개로 제한하고 싶다면 정적(static)으로 선언해야한다. (정의가아님)

    2) 선언만해서 사용가능함

    3) 정의를 굳이해야하는 상황인경우 구현파일에서 정의한다.

      가. const int test::numTurns; (, 값이 주어지지 않음)

      나. 이유 - 선언시점에 주어지기때문

    3) 예외사항 - 구식컴파일러 경우, 2) 못받아들이는경우가 있음

      가. 이때는 정의부에 값을 정의

      나. 이와 같은 상황에서 나열자둔갑술(enum 사용)하는 방법도 있음

 

 

4. #define 오용사례 - 매크로 함수

 

#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b))

  (1) 단점1 - 매크로본문에 들어있는 인자마다 반드시 괄호를 써줘야함..

  (2) 단점2 - CALL_WITH_MAX(++a,b) // a = 10, b = 5; 일때 어떻게 될까?   

 

 

5. 4번항목에 대한 대안으로 인라인 함수에 대한 템플릿을 사용해보자.

template<typename T>
inline void callWithMax(const T& a, const T& b){
f(a,b);
}

  (1) 장점 - 괄호 사용할필요없음, 유효범위 규칙을따라감

 

! 결론

  1. 단순 상수를 쓸때는, #define 보다 const 객체 혹은 enum을 우선 생각하자

  2. 함수처럼 쓰이는 매크로를 사용할때, #define 매크로 대신 inline을 우선 생각하자.

댓글