항목
1. C++를 언어들의 연합체로 바라보는 안목은 필수
■ C++ 이란? 상관 관계가 있는 여러 언어들의 연합체( federation)
C++를 구성하는 요소들은 각각의 규칙을 가지고 있다.
■ C++ 구성요소
1) C
2) 객체 지향 개념의 C++ : 클래스, 캡슐화, 상속, 다형성, 가상 함수( 동적 바인딩 ) 등
3) 템플릿 C++ : 새로운 프로그래밍 패러다임 파생 -> 템플릿 메타프로그래밍( TMP )
4) STL : 템플릿 라이브러리( 컨테이너 / 반복자 / 알고리즘 / 함수 객체 ... )
항목
2. #define을 쓰려거든 cosnt, enum, inline을 떠올리자
부제 : “가급적 선행처리자( define )보다 컴파일러를 더 가까이 하자”
■ define 키워드 단점
1) define 관련 컴파일 에러시 에러메세지 내용이 직관적이지 못하다.
/*
다음 define 관련하여 컴파일 오류가 생길 경우
에러 메세지에서 'MAX_COUNT' 어쩌구는 거론되지않고
'100'이라는 숫자만 거론됨. ;;;
*/
#define MAX_COUNT 100 |
■ define을 상수( const )로 교체하라
1) 부동소수점을 쓸 경우에는 define을 썻을 때보다 최종코드의 크기가 작아 질 수 있다.
2) 기호 테이블에 들어가며 컴파일 문제 발생시 정확한 위치를 직관적으로 표시해준다.
■ define -> const 변경시 유의점
1) 상수 포인터를 정의하는 경우
/*
포인터와 가르키는 대상까지 const로 선언해주자.
*/
const char * const authorName = "Scott Meyers";
/*
char* 가 싫다면 string으로 대체
*/
const std::string authorName("SocttMeyers"); |
// .h file
class CostEstimate
{
private :
static const double FudgeFactor;
};
// .cpp file
const double CostEstimate::FudgeFactor = 1.35; |
■ 클래스 내에서 상수가 필요할때는 enum 이 최고!
1) const보다 #define에 가깝다. int 자료형으로 취급되며 상수값만 유효하다.
2) 메모리에 할당 되지 않는다.
3) 클래스내에서의 enum은 다양한 설계에 유용하게 활용된다.
템플릿 메타프로그래밍의 핵심 기법이기도 하다.
■ 함수처럼 쓰이는 매크로로 만들고자 한다면 #define 매크로 보다 inline 함수를 우선 생각하자.
1) #define 매크로 잘못 사용 한 예
#define CALL_WITH_MAX(a,b) ( (a)>(b) ? (a):(b) ) // 매크로 전체를 ()로 감싸지 않으면 책임못짐;;
int a = 5;
int b = 0;
CALL_WITH_MAX( ++a, b ); // a는 2번 증가! 뭥미;;;
CALL_WITH_MAX( ++a, b+10 ); // a는 1번 증가! |
2) inline 함수 템플릿
template< typename T >
inline int callwithMax( const T& a, const T& b )
{
return ( a > b ? a : b );
} |
항목 3.
낌새만 보이면 const를 들이대 보자!
■ const 의미 해석법
const가 *표의 왼쪽 : 포인터가 가르키는 대상이 상수
const가 *표의 오른쪽 : 포인터 자체가 상수
항목 4. 객체를 사용하기 전에 반드시 그 객체를 초기화하자
■ 대입과 초기화를 헷갈리지 말자
// [대입] 기본 생성자 호출 -> 대입 연산자 호출!
Test::Test( const std::string& name,
const std::string& address,
const std::list<PhoneNumber>& phones )
{
theName = name;
theAddress = address;
thePhones = phones;
nCount = 0;
} |
- C++ 규칙에에 의하면 어떤 객체이든 그 객체의 데이터 맴버는
생성자의 본문이 실행되기 전에 초기화 되어야 한다고 명기 되어있다.
이방법을 '초기화'라고 생각하지 말자.
// [초기화] 복사 생성자 한번 호출
Test::Test( const std::string& name,
const std::string& address,
const std::list<PhoneNumber>& phones )
: theName(name),
theAddress(address),
thePhones(phones),
nCount(0)
{
/* Nothing */
} |
- 자신의 코딩 정책으로 '맴버 초기화 리스트'를 적용하자. ( 습관화 / 의무화 )
- 만약에 나열된 초기화할 객체가 많아 길어지는게 마음에 걸린다면 ???
대입으로도 초기화가 가능한 데이터 맴버들을 빼내어 별도의 함수( ex. init() )로 옮기는 것도 방법이다.
■ 초기화 순서
1) 기본 클래스는 파생 클래스보다 먼저 초기화 된다.
2) 클래스 데이터 맴버는 그들이 선언된 순서대로 초기화된다.
가급적 선언된 파라메타 순서 그대로 초기화 해주는 습관을 기르자
■ 정적 객체 ( static object
)
extern / static 키워드를 사용하여 선언한 객체!!
- 종류
1) 전역 객체
2) 네임스페이스 유효범위에서 정의된 객체
3) 클래스 안에서 static으로 선언된 객체
4) 함수 안에서 static으로 선언된 객체( 지역 전역 객체 )
5) 유효범위에서 static으로 선언된 객체
- 문제가 발생 할 수 있는 부분
별개의 번역 단위에서 정의된 비지역 정적 객체들의 초기화 순서는 ‘정해져 있지 않다’
- 해결책( Singleton pattern )
함수를 두어 최초 호출시 객체를 생성하고 그 이후로는 참조자만 반환해주자.class FileSystem { ... };
FilesSystem& tfs()
{
static FileSystem fs;
return fs;
} |
비지역 정적 객체 -> 지역 정적 객체로 교채!!!
'비공개' 카테고리의 다른 글
[ Effective C++ ] Item 3. 자원관리 (0) | 2011.07.07 |
---|---|
[ Effective C++ ] Item 2. 생성자, 소멸자 및 대입 연산자 (0) | 2011.07.07 |
[ Effective C++ ] Intro (0) | 2011.07.07 |
표준 C++ 라이브러리의 주요 구성요소( C++98 에 명시 ) (0) | 2011.07.07 |
TcMalloc lib 적용 시도!!! (0) | 2011.06.27 |