방프리
16.07.14. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목1, 2) 본문
항목 1 : C++를 언어들의 연합체로 바라보는 안목은 필수
*C++를 사용한 효과적인 프로그래밍 규칙은 경우에 따라 달라진다. 그 경우란, C++의
어떤 부분을 사용하느냐이다.
항목 2 : #define을 쓰려거든 const, enum, inline을 떠올리자
제목에서도 알 수 있듯이 #define 키워드보다 const, enum이나 혹은 inline을 좀 더 활용하자는 것이다.
이유인 즉 컴파일 시점에서 오류 찾기, 또는 메모리 할당 등 여러 이유 때문이다.
다음 예제를 보면서 알아보자
ex)
#define EPSILONE 0.0001f
만약 이 define 구문이 컴파일러 입장에서는 어떤 식으로 보일까?
컴파일 시점에서 define 키워드가 자체적으로 EPSILONE 이라는 문자열을 밀어버리고
그 위치에 대신하여 0.0001f 값을 넣는다. 다시 말해서 EPSILONE 이라는 것은 애초에
컴파일러 입장에서는 존재하지 않는 것으로 본다는 뜻이다.
이로 인해 우리는 여러가지 곤란한 상황에 직면하게 된다.
그 중 첫 번째가 바로EPSILONE이 들어간 구문에서 컴파일 에러 발생 시 메시지에 대한 것이다.
분명 우리는 EPSILONE이라는 단어를 사용했음에도 불구하고 에러 메시지에서는 0.0001 라는 단어만
나온다. 만약 우리가 직접 #define을 작성했다면 알 수 있겠지만, 그러지 않았을 경우 우리는 어디서
에러가 발생하였는지 전혀 알 수 없다. 왜냐하면 앞에서도 말했 듯 EPSILONE이라는 단어 자체는
#define 구문에서 밀어버렸기 때문이다. 그러니 컴파일러 입장에서는 EPSILONE이라는 것이 아예
없다는 가정하에 해석을 진행하기 때문이다.
그러면 어떤 방식으로 해결해야 하는가? 이 때 필요한 것이 바로 const, 상수를 쓰는 것이다.
ex)
const float Epsilone= 0.0001f;
Epsilone은 언어 차원에서 지원하는 상수 타입의 데이터이기 때문에 당연히 컴파일러의 눈에도
보이고 기호 테이블에도 들어간다. (매크로에서는 EPSILONE이란 단어를 기호테이블에 추가X)
또한 #define의 경우 사용할 때마다 메모리가 할당되므로 코드에서 호출한 횟수만큼 계속
복사가 이루어지지만, const의 경우엔 사본 복사할 필요없이 원본 자체가 들어가기 때문에
최종 코드 크기에서도 차이가 난다.
///////////////////////////////////////////////////////////
위의 내용과는 별개로 #define을 매크로 상수로 만들 때 주의할 점
1. 상수 포인터( constant pointer )를 정의하는 경우
- 상수 정의는 대개 해더 파일에 넣는 것이 상례, 포인터는 꼭 const로 선언 그리고 포인터가 가리키는 대상까지 const로 선언
ex) const char * const name = "홍길동";
const std::string name = "홍길동"; //char* 보단 string객체를 사용하는 것을 추천
int id = 10;
const int* const pID = &id;
2. 클래스 멤버로 상수를 정의하는 경우, 즉 클래스 상수를 정의하는 경우
ex)
class GamePlayer
{
private :
static const int NumTurns = 5; //상수 선언
int score[NumTurns]; //상수를 사용하는 부분
}
*주의 할 점
NumTurns 은 정의가 아닌 선언이라고 하는 것이 맞다. 정적 멤버로 만들어지는 정수류 타입의 클래스
내부 상수는 예외로 정의라 표현하지 않는다.
예외적으로 컴파일러가 정의를 달라고 에러메시지를 날릴 경우 다음과 같이 정의를 제공하면 된다.
const int GamePlayer::NumTurns;
이 때 클래스 상수의 정의는 구현 파일에 두고, 헤더 파일에는 두지 않는다.
만일 클래스 상수를 #define으로 만들려고 한다면 방법 자체가 말이 되지 않는다.
(하지만 c++11 표준에서는 바뀌었다. define의 키워드로도 변수의 범위 설정이 가능해졌다.)
'C++ > Effective C++' 카테고리의 다른 글
17.07.04. Effective C++ 2. 생성자, 소멸자 및 대입 연산자 (항목8) (0) | 2020.01.05 |
---|---|
17.6.13. Effective C++ 2. 생성자, 소멸자 및 대입 연산자 (항목7) (0) | 2020.01.05 |
16.1.28. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목5, 6) (0) | 2020.01.04 |
16.07.20. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목4) (0) | 2020.01.04 |
16.07.15. Effective C++ 1. C++에 왔으면 C++의 법을 따릅시다. (항목3) (0) | 2020.01.03 |