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

J·2025년 11월 26일

Effective C++

목록 보기
4/5

※ Effective c++ 내용을 토대로 개인적인 생각이 추가되다.

"가능하면 전처리기보다는 컴파일러를 가까이 하자"

#define ASPECT_RATIO 1.653

#define을 사용하면

  • 소스 코드가 컴파일러로 넘어가기 전에 전처리기가 해당되는 문자/숫자로 변경
  • 기호 테이블 (변수, 함수, 클래스 등 모든 식별자에 대한 메타 데이터를 관리하는 테이블) 에도 이름이 들어가지 않기 때문에 디버깅하기도 쉽지 않다.

=> 매크로 대신 상수를 사용하도록 한다.

const double AspectRatio = 1.653;

  • 상수타입의 데이터이기 때문에 컴파일러가 확인할 수 있음. 또한 매크로를 활용하면 모든 ASPECT_RATIO가 1.653(리터럴)로 모두 바뀌지만,
    상수 AspectRatio를 사용하면 사본은 딱 1개만 생김

#define을 상수로 교체하려는 경우 주의할 점

  • 상수 포인터를 정의하는 경우
    불변의 형태 (const char* const / const std::string)으로 사용

  • 클래스 멤버로 상수를 정의 하는 경우
    static 으로 정의



나열자 둔갑술

  • 클래스를 컴파일하는 도중 클래스 상수의 값이 필요할 때
class GamePlayer
{
	private :
    
    int scores[클래스 상수 필요];
}

컴파일러가 정적 클래스 상수에 대한 클래스 내 초기화를 허락하지 않는다면
enum을 정적 상수 대신 사용하는 방법

class GamePlayer
{
	private :
    enum
    {
    	NumTurns = 5;
	}
    int scores[NumTurns];
}
  • 나열자 둔갑술은 const보다는 #define에 가깝다. (컴파일 타임에 처리되긴 하지만 상수 리터럴이고, 주소를 가지지 않음)

  • 이 나열자 둔갑술은 템플릿 메타 프로그래밍의 핵심 기법이기도 하다.

매크로 함수는 템플릿 함수로 사용하도록 하자.

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

int a = 5, b = 0;

CALL_WITH_MAX(++a, b); // 여기서 문제!! a는 두 번증가한다. 
CALL_WITH_MAX(a, b + 10) ; // 여기서 a는 한 번 증가한다.

// 문제가 발생할 수 있다. 

=> 기존 매크로의 효율의 유지 + 정규 함수의 동작방식 및 타입 안전성까지 취할 수 있는 함수 템플릿을 사용하도록 한다.

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

profile
낙서장

0개의 댓글