Chap 1. C++에 왔으면 C++의 법을 따릅시다.
항목 1. C++를 언어들의 연합체(federation) 로 바라보는 안목은 필수
C++는 한 가지 프로그래밍 규칙 아래 구성된 통합언어(unified language)가 아니라 네 가지 하위 언어들의 연합체(federation) 라고 보는 것이 언어를 이해하기에 좋다.
- C
- 블록, 문장, 선행 처리자, 기본제공 데이터타입, 배열, 포인터 etc…
- OOP로써의 C++
- 클래스를 사용하는 C : 클래스 , 캡슐화, 상속, 다형성, 가상 함수 etc
- 템플릿 C++
- Template Meta-programming : TMP
- STL
- 템플릿 라이브러리 : container / iterator / algorithm / function object
항목 2. #define을 쓰려거든const, enum, inline을 떠올리자.
매크로인 #define를 수식이나 상수에 사용하는 것은 떄때로 예측할 수 없는 결과를 가져올 수 있으며 , 디버깅에 있어서 비효율적이다. 일례로 아래와 같은 컴파일 에러를 생각해 보자.
|
|
컴파일러로 코드가 넘어간 후에는ASPECT_RATIO가 symbolic name으로 남지 않고,숫자 상수로 대체되어 버린다. 때문에 컴파일러의 기호 테이블에 들어가 있기 때문에 컴파일 에러라도 나면, 복잡한 코드에서는 이를 바로잡기가 쉽지 않다. 특히나 매크로 함수는 큰 재앙이 될 수도 있다.
|
|
위와 함수의 경우 a는 7이 되고, 아래의 경우는 6이 되어버린다. 의도되지 않은 결과가 나와버린다.
상수를 선언하는 올바른 코드는 아래와 같다.
|
|
클래스 안에서 상수를 사용하고 싶을 때는 static const 혹은 enum을 사용하자.
|
|
매크로 함수의 경우, template function을 사용하면 매크로의 효율적인 코드의 측면을 가져갈 수 있다.
항목 3. 낌새만 보이면 const를 들이대 보자.
const는 컴파일러가 해당 변수 값에 대한 제약을 단단히 지켜준다는 점에서 강력하고 매력적인 도구이다. 다양한 const의 사용 예를 분석해 보자.
|
|
규칙이 조금은 헷갈리긴 하지만 표시를 기준으로, 왼쪽에 const는 data를 상수로 취취한다. 반면 오른쪽에 있는 const는 포인터 자체를 상수로 취하게 된다. 이는 다음 예를 통해 좀 더 명확히 구분이 가능하다.
|
|
위의 두 가지 경우에 대해서 모두 가능한 문법이며, 둘 다 int 형의 data가 상수임을 의미한다. f1 방식이 일반적이긴 하나, 둘 다 옳은 표현식이므로 기억해두자.
상수 객체를 생성할 경우에는 그에 맞추어 상수 멤버함수도 정의해줄 필요가 있다. 다음 예제를 보자.
|
|
const char& operator[] (std::size_t pos) const
에서 중요한 점은 앞의 const는 return 값인 char&가 상수임을 뜻한다. 반면 뒤의 const는 이 멤버 함수가 상수형으로 정의되었으며, 이는 상수 객체에 대해서 적용되는 함수임을 나타내는 부분이다.
- 추가적으로 공부가 더 필요한 부분
- 비트수준 상수성(bitwise constness) / 논리적 상수성(logical constness)
- const_cast, static_cast의 사용 방법 및 사용 예시 이해
항목 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자.
초기화 되지 않은 채 생성된 변수들은 어디에선가 큰 문제를 일으킬 소지가 다분하다. 정의되지 않은 동작이 발생할 가능성이 높기 때문이다. 최악의 경우에는 어떤 플랫폼에서 미초기화 객체를 읽기만 해도 프로그램이 다운되기도 한다. 디버깅을 최대한 줄이기 위해서는 초기화를 하는 것이 효과적이다.
- built-in type의 객체들은 직접 손으로 초기화하자.
- 생성자에서는 멤버 초기화 리스트를 사용하자.
- non-local한 객체는 local하게 바꾸어 사용하자. (non-local한 객체를 만들면 translation unit 단계에서 정의되지 않은 동작이 일어날 수 있다.)
- Bad Example
global한 변수인 tfs가 중간에 컴파일러 상 어떤 멤버 초기화 과정을 뒤죽박죽으로 할 지 알 수 없어서 위험하다.
|
|
- Good Example
tfs()가 local하게 선언되어 있으며, 이는 C++ 컴파일러상 반드시 멤버 초기화 과정을 거치므로 안전하다.
|
|