개요
이전에 Effective C++을 원서로 보며 공부한 것을 정리해 올렸었는데
아무래도 영어책이다 보니 집중도 덜 되고, 학습에 시간이 좀 더 소요되어 이번에는 번역서를 읽고 정리해 올려보기로 했습니다.
이번에는 끝까지 읽을 수 있기를...
https://product.kyobobook.co.kr/detail/S000001962302
Effective C++ | 스콧 마이어스 - 교보문고
Effective C++ | [Effective C++]은 C++ 프로그래밍과 설계 기술을 향상시켜 주는 55가지 명쾌한 테크닉을 모은 책이다.
product.kyobobook.co.kr
Item1: C++을 연합체로 생각하자
C++를 단일 언어로 생각하기 보다는 언어의 연합체로서 생각해보는 감각을 키워야합니다.
C++은 C언어, 객체 지향 개념, 템플릿 개념, STL이라는 하위 언어의 집합인 것입니다.
하위 언어들은 서로 다른 강점이 있기 때문에 이를 고려해야 합니다.
Item2: #define 대신 const, enum, inline을 선호하자
#define 으로 선언된 상수의 경우 전처리기가 해당 값이 쓰인 곳을 정의한 이름이 아니라 실제 값으로 바꿔치기 합니다.
다만 이 경우에 문제가 생겼을 경우 추적이 힘듭니다.


위의 경우 일반적인 변수와 #define으로 지정한 상수인데요, 이를 대입하는 어셈블리 코드를 실제로 보면,
#define의 경우 값 자체를 그대로 넣는 것을 볼 수 있고, 일반 값의 경우 레지스터에 로드한 후 이를 활용하는 것을 볼 수 있습니다.
명령을 덜 하니까 좋은거라고 생각할 수도 있지만 아래와 같이 #define으로 만든 이름의 값은 찾을 수 없으며

애초에 상수 값이 들어있기 때문에 어떤 이름이었는지도 디버깅을 통해 알 방법이 없습니다.
그리고 클래스 내의 static 상수를 사용할 때도 마찬가지입니다.
애초에 #define은 딱히 의미가 없습니다.
기본적으로는 클래스 내에 static 값을 사용할 때는 선언과 정의를 분리해 헤더에는 선언, 구현파일에는 정의를 적습니다.
그렇게 하지 않으면 실제 메모리에 값이 존재하지 않아 오류를 일으킬 수 있기 때문이죠 (예전 컴파일러 기준)
이를 방지하기 위해 enum hack같은 방식을 이용하기도 했습니다.
현대 C++17이상의 컴파일러에서는 inline static constexpr을 통해 상수를 정의하면 헤더에 정의를 해도 문제가 생기지 않습니다.
inline키워드는 여러 Translation Unit(TU)에 있어도 하나로 취급하기 때문입니다.
추가적으로 상수뿐만이 아니라 함수에서도 inline은 #define의 완벽한 대체재입니다.
#define을 통해 매크로 함수를 만들 수 있습니다. 이는 함수호출 오버헤드 없이 함수를 부를 수 있다는 장점이 있지만, 의도하지 않은 결과를 일으킬 수 있습니다.
따라서 만약에 A.h에 정의한 함수를 B.cpp와 C.cpp에서 사용할 때 A에 정의한 함수가 일반적인 함수라면 링크 오류가 발생하지만, inline함수라면 오류가 발생하지 않게됩니다.
Item3: const를 많이 사용하자
const는 컴파일러에게 해당 값이 변하지 않을 것임을 알려줍니다.
물론 주소를 얻어 포인터로 찔러 값을 변경시킨다면 이걸 막을 방법은 없지만 const를 사용하면 일차적인 가드를 해주며, 해당 코드를 보는 사람에게 이 값이 변하면 안된다는 것을 인지시켜주는 역할도됩니다.
const int* const a; 같이 있을 때 const의 역할이 다름을 인지합시다.
그리고 멤버 함수에 사용하는 const는 해당 클래스 객체 (*this)가 const임을 의미합니다.
따라서 해당 this안의 멤버를 수정할 수 없게 합니다.
추가적으로 상수 멤버와 비상수 멤버의 함수를 각각 만들었는데 코드가 중복되는 경우 캐스팅을 통해서 중복을 줄여볼 수 있습니다.
const_cast<return_type>(static_cast<const T>(*this))와 같은 형식으로요
비상수 함수 내에서 코드 중복을 피하기 위해 상수 함수로 변환하는 것은 할 수 있지만, 상수 함수내에서 비상수는 하면 안됩니다.
const함수의 범위가 더 작기 때문이죠
Item4: 객체 사용 전에는 반드시 초기화하자.
C++의 객체는 확실히 초기에 초기화가 되어있다는 보장이 없습니다.
따라서 안전하게 개발하기 위해서는 언제나 변수를 미리 초기화 하는 것이 좋습니다.
초기화 리스트(initialize list)
초기화 리스트를 사용하면 대입에 비해 효율적일 수 있습니다.
초기화 리스트를 사용하면 해당 타입의 특정 생성자(인자에 따른)를 호출하지만,
사용하지않고 별도로 대입한다면, 기본 생성자 호출 후, 대입 연산자를 사용합니다.


물론 기본 타입의 경우 별 차이가 없겠지만 통일해 초기화 리스트를 사용하는 습관을 들이는 편이 좋겠습니다.
특히 const타입 멤버가 있다면 초기화리스트를 사용하면 해당 객체의 const 타입 인자를 받는 생성자를 호출하겠지만, 대입은 아예 불가능합니다
Local, Non-Local static object
함수 내에서 사용되는 static 객체를 local static object, 그 외의 외부의 object를 non-local static object라고 부릅니다.
이 때 non-local static object 간에는 초기화 순서를 보장할 수 없습니다. 그리고 local static object는 처음으로 해당 객체를 정의했을 때 초기화 됩니다.
그렇기 때문에 non-local static object 대신에 local static object를 생성해 반환하는 방식을 통해 시점을 제어하는 방식을 사용할 수 있습니다.
마치 singleton 패턴과 유사합니다.
'C, C++ > Effective C++' 카테고리의 다른 글
| [Effective C++] 3장 자원 관리 (0) | 2026.02.11 |
|---|---|
| [Effective C++] 2장 C++의 규칙 따르자 (0) | 2026.02.06 |
| 7장 템플릿과 제네릭 프로그래밍 (0) | 2025.04.02 |
| 6장 상속과 객체 지향 디자인 (0) | 2025.03.28 |
| 5장 구현 (0) | 2025.03.25 |