" 가급적 선행 처리자보다 컴파일러를 더 가까이 하자 "
#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 매크로보다 인라인 함수를 우선 생각합시다.
'0x0001 > Effective C++' 카테고리의 다른 글
[Effective C++] 항목 6 : 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해버리자 (0) | 2019.02.10 |
---|---|
[Effective C++] 항목 5 : C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 (0) | 2019.02.09 |
[Effective C++] 항목 4 : 객체를 사용하기 전에 반드시 그 객체를 초기화 하자 (0) | 2019.02.09 |
[Effective C++] 항목 3 : 낌새만 보이면 const를 들이대 보자! (0) | 2019.02.09 |
[Effective C++] 항목 0 : 시작 하며 (0) | 2019.02.09 |