#define으로 선언한 상수는 컴파일 과정중 오류 발생시 정확한 이름을 밝히지 않는다.
#define NUMBER 0
int main()
{
int result = 10 / NUMBER;
return 0;
}
만약 다음과 같은 코드를 실행 하면 NUMBER가 0이기 때문에 컴파일이 안되고 오류가 발생 할 것이다.
하지만 오류에는 0으로 나눌 수 없다는 메시지만 나오지 NUMBER에 대해서는 언급 되지 않는다. 그 이유는 컴파일시에 전처리단계에서 NUMBER는 모두 0으로 치환되기 때문이다. 그래서 우리는 0이 무엇인지 일일이 찾아다녀야 하는 불편함이 있다. 이때 만약 const를 이용하여 상수로 선언을 하였다면 기호 테이블에 입력되어 오류에도 0으로 표시되는것이 아니라 상수 명으로 잘 나올 것이다.
다음으로는 나열자 둔갑술(enum hack)에 관한 내용인데 const는 컴파일러의 성능에 따라 메모리를 할당할 가능성이 있고 주소를 추적당할 가능성이 있어서 enum을 이용하여 이를 해결하자는 것이다.
class BookStore
{
private:
enum { MaxNumberOfBook = 100 };
int storage[MaxNumberOfBook];
}
이런식으로 말이다. 그런데 이것은 오류가 발생시 똑같이 숫자로 표시되는 특성이 있었다. 이 책에서 추천하는 방법 이긴 하지만 굳이 이렇게 쓸 바에는 #define이 오히려 더 나을 수도 있겠다는 생각이 든다.
다음으로는 매크로 함수 대신에 inline함수를 쓰라는 것이다.
#define GET_MAX(a, b) (a) > (b) ? (a) : (b)
int main()
{
int a = 10;
int b = 4;
int max = GET_MAX(++a, b);
max = GET_MAX(++a, b+10);
}
자 위와 같은 코드에서 우리가 원하는 방향이라면 최종적으로 a는 12여야 정상일 것이다. 하지만 프로그램 종료 시점에서 a는 13이다. 왜 그럴까? 매크로 함수에서 매개변수를 괄호로 감싸는데 이것이 바로 원인이다. (a)가 실행 될때마다 그 안에 있는 수식이 계속 호출된다고 생각하면 된다. 첫번째 max에서 (a) > (b) 부분에서 ++a가 한 번, 그 후 (a)가 더 크므로 (a)가 또 실행되면서 ++a가 호출이 되는 것이다. 같은 방식으로 두번째에서는 ++a가 한번 호출된다. 이러한 불상사를 막으려면 간단하다. 템플릿 인라인 함수를 쓰면 된다.
template<typename T>
inline T getMax(const T& a, const T& b)
{
return a > b ? a : b;
}
int main()
{
int a = 10;
int b = 4;
int max = getMax(++a, b);
max = getMax(++a, b+10);
}
이렇게 하면 a는 최종적으로 12로 우리가 원하던 답이 나온다. 그래서 이와 같은 상황이 예상될 경우에는 꼭 인라인 함수를 쓰도록 하자. 그리고 애초부터 매크로 함수보다 인라인 함수를 애용하면 이런 문제를 사전에 방지 할 수 있지 않을까 싶다.
'C++ > Effective C++' 카테고리의 다른 글
항목 7 다형성을 가진 기본 클래스에서는 소멸자를 반드시 가상 소멸자로 선언하자 (0) | 2024.01.18 |
---|---|
항목 6 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해 버리자 (2) | 2024.01.18 |
항목 4 객체를 사용하기 전에 반드시 그 객체를 초기화 하자 (0) | 2024.01.18 |
항목 3 낌새만 보이면 const를 들이대 보자! (0) | 2024.01.17 |
Effective C++ 스타트 (0) | 2024.01.17 |