" 가급적 선행 처리자보다 컴파일러를 더 가까이 하자 "

 

 #define의 단점

 

1. 컴파일 에러가 발생하면 찾아내기가 쉽지 않다.

#define ASPECT_RATIO 1.653

 

위의 코드는 컴파일 되기 전에 선행처리자가 소스에서 ASPECT_RATIO라는 이름을 밀어버리고 1.653으로 전부 바꿔버리기 때문에 에러메시지에서 ASPECT_RATIO 라는 이름을 확인 할 수 없고, 특히 남이 쓴 코드일때 이값에 대한 출처를 파악하기 어렵다.

 

 

 

2. 코드의 크기가 커진다.

 매크로를 쓰면 코드에 ASPECT_RATIO가 등장하기만 하면 선행 처리자에 의해 1.653으로 모두 바뀌면서 사본의 갯수가 늘어난다.  

 

위의 1, 2번 해결방안은?

 

const double AspectRatio = 1.653;

위의 코드처럼 상수를 쓰는 것 입니다. 상수이기때문에 당연히 컴파일러에서 알아 차릴 수 있습니다.

또한 상수는 아무리 여러 번 쓰이더라도 사본은 딱 한 개만 생깁니다.

 

 

여기서 잠깐 #define을 const 변수로 바꿀때 주의할 점이 있습니다.

1. 상수포인터를 정의할때, 특히 문자열 상수일 경우 해당문자열의 변경이 없으므로

const char * const cClass = "학급"; // 포인터 앞뒤로 변경을 막아준다, ( 값, 주소값 모두 X )

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

어떤 상수의 유효번위를 클래스로 한정하고자 할 때는 그 상수를 멤버로 만들어야 하는데, 그 상수의 사본 개수가 한 개를 넘지 못하게 하고 싶다면, 정적 멤버로 만들어야한다.

class GamePlayer {

private:

 static const int NumTurns = 5;

 int scores[NumTurns];

};

 

위의 클래스 처럼 상수를 멤버로 가질때, 구식 컴파일러에선 작동을 하지 않을 때가 있다.

이때 나열자 둔값술(enum)을 많이 사용합니다.

class GamePlayer {

private:

 enum { NUM_TURN = 5 };

 int scores[NUM_TURN];

};

 

enum을 쓰는데도 이점이 있습니다.

 

혹시 enum대신 const 정수를 선언해서 쓰는데 다른사람이 이 상수변수의 주소를 얻는다든지 참조자를 쓰는것이 싫다면, 나열자 둔값술(enum)은 좋은 자물쇠가 됩니다.

enum은 #define처럼 어떤 형태의 쓸데 없는 메모리 할당도 절대 저지르지 않습니다.

 

 

 

3. 매크로 함수 사용시 문제를 야기 할 수 있다.

 

매크로 함수를 작성할때는 ()는 무조건 씌워 줍니다.

예를들어 #define MUL(a, b) a * b

MUL( 1+1, 2+2 )->1 + 1 * 2 + 2로 바뀌게 연산자 우선순위에 따라 우리가 의도했던 계산식이 아닐수 있다.

 

또한,

#define CALL_WITH_MAX(a, b) function( (a) > (b) ? (a) : (b) )// a와 b 중 큰것을 function에 넘겨 호출

 

int a = 5, b = 0;

CALL_WITH_MAX(++a, b);          // ++a > b ? ++a : b ( ++a가 두번 증가 된다, a > b 크므로 )

CALL_WITH_MAX(++a, b + 10);   // ++a > b+10 ? ++a : b+10 ( ++a가 한번 증가된다 )

 

위의 코드 처럼 우리는 ++a를 한번 하고 싶지만, 선행처리기에 의해 바뀌면서, 이상한 현상이 되므로 주의를 귀울여야 합니다.

 

물론 위의 해결방안도 제시하는데, 바로 inline(인라인)함수에 대한 템플릿을 준비하는 것입니다.

template<typename T>

inline void callWithMax( const T& a, const T& b)

{

  function( a > b ? a : b );

}

 

매크로 함수를 작성하는 이유?

함수호출의 오버헤드를 일으키지 않으려고 함에 있습니다.

 

매크로 함수보다 인라인함수의 이점은 ?

 

1. 함수 본문에 괄호로 분칠할 필요가 없고

2. 이자를 여러번 평가할지도 모른다는 걱정도 없어집니다.

3. 함수이기 때문에 유효범위 및 접근 규칙을 그대로 따라갑니다.

 

 

이것 만은 잊지 말자!

◆ 단순한 상수를 쓸때는, #define 보다 const 객체 혹은 enum을 우선 생각합시다.

◆ 함수처럼 쓰이는 매크로를 만들려면, #define 매크로보다 인라인 함수를 우선 생각합시다.



+ Recent posts