Hyun2and
[Effective C++] 1. C++ 본문
728x90
1: C++ 언어들의 연합체
- C++는 다중패러다임 프로그래밍 언어 라고 부른다
- 절차적 프로그래밍을 기본으로 하여 객체 지향, 함수식, 일반화 프로그래밍, 메타 프로그래밍을 포함한다
- TMP : 템플릿 메타프로그래밍.
- C++의 일반화 프로그래밍 부분
- STL : 템플릿 라이브러리
- 컨테이너, 반복자, 알고리즘, 함수 객체
- C와의 차이점
- C에서는 기본적으로 값 전달이 참조 전달보다 좋다.
- C++에서는 생성자, 소멸자가 생기고, 템플릿을 쓰다보면 해당 객체의 타입을 알 수 없기 때문에 const 객체 전달이 가장 좋다
- 그러나, STL은 값 전달이 좋다 (C 기반이기 때문에)
2: #define 보다 const, enum, inline
- 컴파일러를 더 가까이하자
- #define 을 쓰면 선행 처리 과정에서 이미 상수로 바뀐다
- 상수 정의는 헤더 파일에 넣는 것이 상례
- 포인터, 포인터가 가리키는 대상 const
- 클래스 내부 상수를 정의하는 경우, static 멤버로 만들어야 한다
- 매크로는 정의되면 컴파일이 끝날 때까지 유효하다
Enum hack 나열자 둔갑술
- C++ 에서는 enumerator 타입에 int 가 놓일 수 있다
enum { NumTurns = 5; } 로 선언하고 int scores[NumTurns]; 해도 문제가 없다
- 동작 방식이 const보다는 #define에 가깝다
- 주소를 얻어내거나 참조자를 쓸 수 없다
- 쓸데없이 메모리가 잡히지 않는다
- 메타프로그래밍 핵심 기법
inline
- 호출 매크로와 비슷한 #define 으로 함수를 많이 정의한다
- 이 경우, 함수 결과에 따라 다른 결과값이 나올 수도 있다
- lnline을 쓰면 동일 계열 함수군 family of functions 를 만들어낸다
- inline으로 선언된 함수는 진짜 함수이기 때문에 유효범위와 접근 규칙을 그대로 따른다 (#define은 전혀 없다)
3: const를 자주 사용하기
- const를 사용하면 이 객체를 외부에서 변경이 불가능해지며, 컴파일러가 이 제약을 단단히 지켜준다.
- 클래스 바깥에서 전역 혹은 네임스페이스 유효범위의 상수를 선언하는 데 쓸 수 있다
- 파일, 함수, 블록 유효범위에서 static으로 선언한 객체에도 const를 붙일 수 있다
- 클래스 내부에서는 정적 멤버 및 비정적 데이터 멤버 모두를 상수로 선언할 수 있다
- STL iterator는 포인터를 본따 만들어졌다. 기본 동작 원리가 T*와 유사
- 반복자는 가리키는 대상 자체는 변경이 가능하다. (반복자 자체를 변경하려면 const_iterator 사용)
Const 멤버 함수
- 해당 멤버 함수가 상수 객체에 호출될 함수라는 것을 알려준다
- 클래스의 인터페이스의 이해가 좋아진다
- 상수 객체를 사용할 수 있게 된다 (객체 전달을 const 참조로 하는 것이 가장 효율적이기 때문)
- const 키워드가 있고, 없는 차이만 있는 함수들은 오버로딩이 가능하다
- 상수성 const 의 개녑
- 비트수준 상수성 bitwise const (물리적 physical) : 어떤 멤버 함수가 그 객체의 어떤 데이터 멤버도 건드리지 않아야 const로 인정함
- 논리적(logical) 상수성 : 일부 몇 비트가 수정되더라도 사용자 수준에서 인식할 수 없다면 const로 인정함→ mutable : 비정적 데이터 멤버를 bitwise const 에서 풀어준다. 약간의 변경만 하고 컴파일러도 피할 수 있다
- → 하지만 , 컴파일러의 검열을 통과하려면 bitwise const를 지켜야 한다.
코드 중복 현상을 피하기
- operate[ ] 를 const, 비 const 로 오버라이딩했을 때, 동일한 operator 연산이므로 같은 내용을 두 번 작성해야 한다 = 코드 중복!
- 비 const 타입 함수에서 const 타입을 호출해주자. *this 타입 캐스팅을 쓰면 된다
4: 객체를 사용하기 전에 반드시 그 객체를 초기화할 것
- C++ 에서는 기본적으로 객체 초기화를 해주지만, 안해주는 경우도 있다
- 규칙이 존재하긴 하지만 복잡하므로… 사용하기 전에 항상 초기화하자
- 대입(alignment) 과 초기화 (initialization) 는 다르다
- 클래스의 생성자에 값을 전달하는 방식은 대입이다. 생성자의 본문이 실행되기 전에 초기화되어야 한다
class A(){
};
A::A(string name, ... ){
thename = name; // alignment
}
A::A(string name, ... ) : thename(name) { // initialization
}
- 특정 값을 넣지 않더라도 초기화해주는 것이 좋다
A::A() : theName(), theAddress(), numTimes(0) {}
객체를 구성하는 데이터의 초기화 순서
- 객체 초기화는 변덕스럽지만, 데이터 초기화 순서는 그렇지 않다
- 기본 클래스는 파생 클래스보다 먼저 초기화된다
- 클래스 데이터 멤버는 선언된 순서대로 초기화된다
- static object : 자신이 생성된 시점부터 프로그램이 끝날 때까지 살아 있는 객체
- 전역 객체
- 네임스페이스 유효범위에서 정의된 객체
- 클래스 안에서 static으로 선언된 객체
- 함수 안에서 static으로 선언된 객체 = local static object
- 파일 유효범위에서 static으로 정의된 객체
(함수 제외하고는 모두 non-local static object)
- translation unit : 컴파일을 통해 하나의 object file을 만드는 바탕이 되는 소스코드
→ 별개의 translation unit에서 정의된 non-local static object들의 초기화 순서는 정해져 있지 않다
→ non-local static object 를 하나씩 맡는 함수를 준비하고 이 안에 객체를 넣는다. → local static 객체로 만든다 (=singleton )
728x90
'공부엔 끝이없다 > Effective C++' 카테고리의 다른 글
[Effective C++] 46: 타입 변환이 바람직할 경우에는 비멤버 함수를 클래스 템플릿 안에 정의해 두자 (0) | 2023.08.06 |
---|---|
[Effective C++] 45: "호환되는 모든 타입" 을 받아들이는 데는 멤버 함수 템플릿이 직방! (0) | 2023.07.31 |
[Effective C++] 44: 매개변수에 독립적인 코드는 템플릿으로부터 분리시키자 (0) | 2023.07.31 |
[Effective C++] 43: 템플릿으로 만들어진 기본 클래스 안의 이름에 접근하는 방법을 알아두자 (1) | 2023.07.23 |
[Effective C++] 0. 서론 (0) | 2023.02.19 |
Comments