[ Effective C++ ] 정리 모음집
" C++ 프로그래머의 필독서, 스콧 마이어스의 Effective C++ 를 읽고 내용 요약 / 정리 "
" 가급적 선행처리자보다 컴파일러를 더 생각하자 "
- 단순한 상수를 쓸 때는, #define보다 const 객체 혹은 enum을 우선 생각하자!
- 함수처럼 쓰이는 매크로를 만들려면, #define 매크로보다 인라인 함수를 우선 생각하자!
[ 매크로 정의 ]
#define ASPECT_RATIO 1.653
[ 상수 선언 ]
const double AspectRatio = 1.653;
[ 상수 포인터 선언 ]
const char* const szName = "Minsu Lighting";
[ 클래스 멤버 상수 선언 ]
class Player
{
private:
static const int NumTurns = 5; // 상수 선언
int scores[NumTurns]; // 상수 사용 부분
}
📢 위 코드를 보면 상수의 '선언'만 있고 '정의'가 없는걸 확인할 수 있는데...
C++에서는 사용하고자 하는 것에 대한 '정의'가 마련되어 있어야 하지만, 정적 멤버로 만들어지는 정수류(각종 정수 타입, char, bool 등) 타입의 클래스 내부 상수는 예외!
📢 하지만 별도의 정의를 제공해야 하는 경우도 있다!
- 클래스 상수의 주소가 필요한 경우!
- 컴파일러가 잘 못 만들어진 관계로 정의를 요구하는 경우
[ 클래스 멤버 상수 정의 ] const int Player::NumTurns;
- 정의는 헤더 파일이 아닌 구현 파일에 둠.
- 클래스 상수의 초기 값은 선언된 시점에 주어졌기 때문에 정의에는 값을 주지 않음.
📢 일부 컴파일러의 경우 위의 문법을 사용하지 못 함
컴파일러가 선언 시점에 초기 값을 주는 것이 맞지 않다고 판단하기 때문인데...
이 때에는 정의 시점에 초기 값을 주면 된다!class CostEstimate { private: static const double FudgeFactor; ... }; . . . const double CostEstimate::FudgeFactor = 1.35;
마찬가지로 선언은 헤더 파일에, 정의는 구현 파일에 위치!
📢 이렇게 끝나면 좋겠지만.... 또 다른 문제가 발생한다.
컴파일 도중 상수의 값이 필요할 때에는 위의 방법들이 통하지 않는다는 것...
이 때에는 enum을 사용 하자!
- const 보다는 #define에 가까운 동작 방식!
enum은 define처럼 주소를 얻을 수 없으므로 주소를 얻는다던지, 참조자를 쓴다던지 하는 행동이 필요 없다면 좋은 자물쇠 역할이 될 것이다! 또 한 쓸데없는 메모리 할당도 일으키지 않는다!
- 상당히 많은 코드에서 쓰이므로 미리 익혀두자!
enum은 템플릿 메타플그래밍의 핵심 기법이기도 함!
[ 매크로 함수 정의 ]
#define CALL_WITH_MAX(a,b) f((a) > (b) ? (a) : (b))
원하는 결과를 얻는 정확한 매크로 함수의 구현은 어려우며, 따라서 디버깅 또한 매우 어렵다!
매크로 함수의 길이가 증가할수록 사용되는 괄호 또한 매우 많아져서 가독성이 떨어짐.
template<typename T>
inline void callWithMax(const T& a, const T& b)
{
f(a > b ? a: b);
}
매크로의 효율성은 유지!
정규 함수의 모든 동작방식 및 타입 안정성 확보 가능!