Effective C++ 정리: 항목 1~5
항목 1: C++를 언어들의 연합체로 바라보는 안목은 필수
C++는 단일 언어가 아니라 다중 패러다임의 결합입니다. 이를 이해하고 적절한 관점으로 접근해야 합니다.
C++의 4가지 주요 관점
- C 스타일: 절차적 프로그래밍, 포인터, 메모리 직접 관리 등.
- 객체지향 스타일: 클래스, 상속, 다형성 등.
- 템플릿 스타일: 컴파일타임 제네릭, 타입 추론 등.
- STL 스타일: 컨테이너, 반복자, 알고리즘, 람다.
➡️ 어떤 기능을 구현할 때 이 중 어떤 스타일이 적절한가를 고민하면서 코딩해야 함.
항목 2: #define을 쓰거든 const, enum, inline을 떠올리자
❌ #define의 문제점
#define A 123
- 단순 텍스트 치환 → 타입 정보 없음
- 에러 시 디버깅 어려움 (에러 메시지에 123만 나옴)
#define SQUARE(x) x * x
int result = SQUARE(2 + 3); // 2 + 3 * 2 + 3 = 11 (!?)
✅ 대안 1: const
const int A = 123; // 타입 안전 + 디버깅 쉬움
✅ 대안 2: enum
enum { MaxSize = 10 }; // 주소를 가질 수 없음 → 진짜 상수
✅ 대안 3: inline
inline int square(int x) { return x * x; } // 타입 안전한 함수
항목 3: 낌새만 보이면 const를 들이대 보자!
포인터와 const 조합
선언 포인터 변경 값 변경
const int* p | ✅ 가능 | ❌ 불가 |
int* const p | ❌ 불가 | ✅ 가능 |
const int* const p | ❌ 불가 | ❌ 불가 |
반복자와 const
std::vector<int> v = {1, 2, 3};
const std::vector<int>::iterator it1 = v.begin();
*it1 = 10; // OK
++it1; // ❌ const iterator이므로 이동 불가
std::vector<int>::const_iterator it2 = v.begin();
*it2 = 10; // ❌ 값 변경 불가
++it2; // OK
함수에서의 const 사용
class A {
public:
int get() const { return value; } // 멤버를 변경하지 않겠다는 약속
private:
int value;
};
항목 4: 객체를 사용하기 전에 반드시 초기화하자
❌ 생성자에서 대입만 하면?
class A {
public:
A(int val) { x = val; } // 기본 생성자 호출 후 대입 (비효율)
private:
int x;
};
✅ 생성자 초기화 리스트 사용
class A {
public:
A(int val) : x(val) {} // 초기화 리스트로 한 번에 초기화
private:
const int x;
};
멤버 초기화 순서
class B {
public:
B() : y(2), x(1) {} // 실제 초기화 순서는 x → y
private:
int x;
int y;
};
➡️ 선언 순서대로 초기화됨!
정적 객체 초기화 순서 문제
// A.cpp
Logger logger;
// B.cpp
Config config;
→ logger가 먼저 초기화되면 config가 아직 준비되지 않은 상태일 수 있음
✅ 해결법: 지역 정적 객체로 대체 (Singleton)
Logger& GetLogger() {
static Logger logger;
return logger;
}
항목 5: 컴파일러가 자동 생성하는 함수를 주의하자
C++는 클래스에 대해 다음 함수를 자동 생성할 수 있습니다:
- 기본 생성자
- 소멸자
- 복사 생성자
- 복사 대입 연산자
암시적 복사 생성자 문제 예시
class A {
public:
A(int& ref) : ref_(ref) {}
private:
int& ref_;
};
A a1(10); // ❌ 임시 값은 참조할 수 없음
A a2 = a1; // 복사 생성자 자동 호출 → 얕은 복사, 위험!
해결: 명시적으로 복사/대입 금지
class A {
public:
A(const A&) = delete;
A& operator=(const A&) = delete;
};
또는 C++98(예전) 방식:
class A {
private:
A(const A&);
A& operator=(const A&);
};
'C++ > Effective C++' 카테고리의 다른 글
Effective C++ 공부 (항목 11 ~ 15) (1) | 2025.06.25 |
---|---|
Effective C++ 공부 (항목 6 ~ 10) (0) | 2025.06.24 |