Post
#define 소스코드의 경우에는 컴파일러에게 넘어가기 전, 선행처리자에서 숫자 상수로 바꾸어버린다.
그래서 #define pie 3.141 이라면
pie라는 이름은 컴파일러가 쓰는 기호 테이블에 들어가지 않고 숫자 상수(3.141)로 대체된다.
CONST
하지만 #define대신에 const를 사용해
const double pie = 3.141; 을 작성한다면 상수타입의 데이터이기 때문에 컴파일러에서도 보이게된다.
그리고 매크로인 #define을 쓰게된다면 3.141의 사본이 등장횟수만큼 코드안에 들어가지만, 상수 타입인 const를 쓰면 사본이 한개만 생성되어 최종 코드의 파일 크기가 더작아지게된다.
※ #define을 상수로 교체할때의 주의할 점
1. 상수 포인터를 정의하는 경우
포인터는 꼭 const로 선언, 포인터가 가리키는 대상까지 const로 선언
const char * const alphabet = "ABCD";
const std::string alphabet = "ABCD";//위보다 더 좋은방법
2. 클래스 멤버로 상수를 정의하는 경우
Class GamePlayer{
private:
static const int NumTurns = 5; // 상수선언
int scores[NumTurns];
...
};
3번째 줄의 코드는 '정의'가 아닌 선언이다. 정적 멤버로 만들어지는 정수류 타입의 클래스 내부 상수는 정의 없이 선언만 해도 아무 문제없다.
const int GamePlayer::NumTurns; //NumTurns정의
하지만 컴파일러가 정의를 달라고 떼쓰는 경우에는 위와 같은 클래스 상수 정의를 '구현파일'에 둔다.
선언된 시점에서 상수의 초기값이 주어지기때문에, 정의에서는 초기값이 주어지면 안된다.
#define으로는 클래스 상수를 정의할 수도, 캡슐화 혜택도 받을 수 없다.
class CostEstimate{
private:
static const double FudgeFactor; //정적 클래스 상수 선언(헤더파일에 두기)
...
};
const double
CostEstimate::FudgeFactor = 1.35; //정적 클래스 상수 정의(구현파일에 두기)
오래된 컴파일러의 경우에는 반대로 선언된 시점에서 초기값을 주는게 아닌, 정의 시점에 초기값을 주도록해야한다.
ENUM
여기서 예외)
Class GamePlayer {
private:
enum {NumTurns = 5 }; //5에대한 기호식 이름으로 만듬
int scores[NumTurns];
...
};
오래된 컴파일러를 배려해서 '나열자 둔갑술'(enum hack) 기법을 활용하자.
나열자 타입의 값은 int가 놓일 곳에도 쓸 수 있다. 원래라면 클래스내 초기화 금지로인해 위의 int scores[NumTurns]같은 배열멤버선언은 오래된 컴파일러에서 동작하지못한다.
INLINE
#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b)) //#define을 쓴 경우
template<typename T> //inline에 대한 Template을 쓴 경우
inline void callWithMax(const T& a, const T& b)
{
f(a>b ? a:b);
}
CALL_WITH_MAX(++a,b);
CALL_WITH_MAX(++a,b+10);
매크로를 작성할 때는 매크로 본문에 들어 있는 인자마다 반드시 괄호를 씌워주어야한다.
하지만 inline을 쓴다면 그런 괄호들을 굳이 씌울 필요가 없다.
이런 눈에 보이는 부분들이 아니더라도
밑의 코드들을 보았을때 #define매크로를 사용한다면 f가 호출되기도 전에 a가 증가하는 횟수가 달라지게 된다.
하지만 inline을 쓴다면 인자를 여러번 평가할지 모른다는 걱정도 없다.
그리고 매크로가 아닌 진짜 함수이기때문에 함수의 유효범위 및 접근규칙을 그대로 따라가기에 기존 매크로의 효율유지는 와 함께 함수의 모든 동작방식 및 타입의 안정성까지 챙길 수 있다.
'STUDY > Effective C++' 카테고리의 다른 글
항목 6: 컴파일러가 만들어낸 함수가 필요 없으면 확실히 이들의 사용을 금해버리자 (0) | 2022.06.23 |
---|---|
항목 5: C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 (0) | 2022.06.23 |
항목 4: 객체를 사용하기 전에 반드시 그 객체를 초기화하자 (0) | 2022.06.23 |
항목 3: 낌새만 보이면 const를 들이대 보자! (0) | 2022.06.18 |
항목1: C++를 언어들의 연합체로 바라보는 안목은 필수 (0) | 2022.06.13 |