반응형
0. 요약
#define 보다는 const, enum, inline을 사용하자!
- 가급적 선행 처리자보다 컴파일러를 더 가까이 하자!
상수 포인터 정의시 const + const(포인터 및 데이터) 사용하자!
클래스 멤버로 상수를 정의하면 정적 멤버로 정의하자!
- static const~~
1. #difine을 쓰면 안되는 이유
#define ASPECT_RATIO 1.653
- ASPECT_RATIO는 컴파일 되기 전에 1.653이라는 숫자로 변경됨
- 따라서 컴파일러는 ASPECT_RATIO를 모름
- 컴파일러가 쓰는 기호 테이블에 포함안됨
- 매크로 변경 지점에서 컴파일 에러 발생 시 디버깅 어려움
- 클래스 상수를 #define으로 만들 수 없다.
- 캡슐화가 안되고, private 성격의 #define은 없다.
2. 상수를 써서 해결 하라!
const double AspectRatio = 1.653;
- AspectRatio는 컴파일러가 알고 있음
- 컴파일을 거친 최종 코드 크기가 #define 썻을 때 보다 작음
- 상수가 부동소수점 실수 타입일 경우
- 매크로를 쓰면 ASPECT_RATIO가 모두 1.653으로 변경되지만
- 상수 AspectRatio는 사본이 한개만 존재
3. #define을 상수로 교체할 때 주의할 점
- 상수 포인터를 정의하는 경우
- 상수 정의는 헤더 파일에 넣는 것이 상례
- 포인터와 가리키는 대상 모두 const로 선언
// 문자열 포인터로 정의하는 경우
const char* const authorName = "Scott Meyers";
// string으로 정의하는 경우
const std::string authorName("Scott Meyers");
- 클래스 멤버로 상수(클래스 상수)를 정의하는 경우
- 정적 멤버(static)로 생성
class GamePlayer {
private:
static const int NumTurns = 5;
int scores[NumTurns];
};
//1. 여기서 NumTurns는 '선언' 된것이다. '정의'가 아님에 주의
//2. 만약 별도의 정의가 필요할 경우 정의 제공 필요
const int GamePlayer::Numturns;
//3. 클래스 상수 정의는 헤더파일에 두지 않고 구현파일에 둔다.
// - 클래스 상수의 초기값은 선언 시점에서 주어지기 때문
- 컴파일이 위의 문법을 허용하지 않을 때
- 오래된 컴파일러에서 발생
- 정적 클래스 멤버가 선언될 때 초기값 설정 허용 안함
- 이 경우 초기값을 상수 정의 시점에 준다.
//헤더 파일에 둔다.
class CostEstimate {
private:
static const double FudgeFactor; // 정의
};
//구현 파일에 둔다.
const double CostEstimate::FudgeFactor = 1.35; // 선언
- 클래스를 컴파일 시 클래스 상수값이 필요한 경우
- 예)GamePlayer::scores 배열 멤버 선언 필요 시
- enum hack 기법 사용
class gamePlayer{
private:
enum { NumTurns = 5};
int scores[NumTurns];
}
- enum hack(나열자 둔갑술)
- const보다는 #define에 가까움
- const의 주소는 알 수 있지만, enum의 주소는 취할 수 없다.
- 선언한 정수 상수의 주소를 다른 사람이 알 수 없게 하려면 enum을 써라!
4. 매크로 함수
- 매크로 함수의 단점
- 매크로 인자 마다 반드시 괄호를 씌워야함
- 괄호가 있어도 예상 불가한 현상 발생 가능(아래 예시 참고)
#define CALL_WITH_MAX(a,b) f((a) > (B) ? (a) : (b))
int a = 5, b = 0;
CALL_WITH_MAX(++a, b);
// a가 두번 증가함
// 비교할 때 (a)에서 한번, 참인 경우 (a)에서 한번
CALL_WITH_MAX(++a, b+10);
// a가 한번 증가함
- inline 함수를 이용해 해결
- 괄호를 매번 쓰지 않아도 되고, 인자가 여러번 평가되지 않음
- callWithMax는 진짜 함수이기 때문에 유효 범위 및 접근 규칙을 그대로 따라감
template<typename T>
inline void callWithMax(const T& a, const T& b){
f(a > b ? a : b);
}
참고
- Effective C++
반응형
'C++ > Effective C++' 카테고리의 다른 글
[Effective C++] 6. 컴파일러가 만들어낸 함수가 필요없으면 확실히 이들의 사용을 금해버리자. (0) | 2021.03.15 |
---|---|
[Effective C++] 5. C++가 은근슬쩍 만들어 호출해 버리는 함수들에 촉각을 세우자 (0) | 2021.03.15 |
[Effective C++] 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자 (0) | 2021.03.15 |
[Effective C++] 3. 낌새만 보이면 const를 들이대 보자 (0) | 2021.03.15 |
[Effective C++] 1. C++를 언어들의 연합체로 바라보는 안목은 필수 (0) | 2021.03.15 |