7. 객체 생성시 괄호(())와 중괄호({})를 구분하라
기존의 변수 초기화 방법에, 중괄호 초기화 방법을 더해 총 4가지의 방법으로 변수를 초기화
이번 항목의 나머지 부분에서는 이러한 등호와 중괄호 구문은 무시
->대체로 C++은 이를 중괄호만 사용한 구문과 동일하게 취급하기 때문에
<중괄호 초기화의 특징>
(1). 이전에는 표현할 수 없었던 방식의 객체 생성을 표현 가능
(2). 비정적 데이터 멤버의 기본 초기화 값을 지정하는 데에도 사용되는데 C++에서는 괄호 없이 "="만 있는 초기화 구문으로도 사용 가능
그러나 복사할 수 없는 객체는 중괄호나 괄호로는 초기화 가능, "="로는 초기화 불가
(3). 내장 기능들 사이의 암묵적 축소 변환(narrowing conversion)을 방지
(4). C++의 가장 성가신 구문 해석에서 자유롭다는 것
(5). 생성자 오버로딩 해소 과정에서 가능한 한 std::initializer_list 매개변수가 있는 생성자와 부합(심지어 겉으로 보기에 그보다 인수들에 더 잘 부합하는 생성자가 있어도).
(6) 괄호와 중괄호의 선택이 의미 있는 차이를 만드는 예는 인수 두 개로 std::vector<수치 타입>을 생성하는 것이다.
8. 0과 NULL보다 nullptr를 선호하라
0, NULL=포인터 X, int
사용 결과: 오버로딩된 함수를 호출했을 때 포인터를 받는 오버로딩된 함수가 호출되는 일 x
nulltr=포인터 타입
사용결과: 오버로딩이 예상과 다르게 해소되는 일 X, 코드 명확도 높여줌
9. typedef보다 별칭 선언을 선호하라 범위 없는 enum보다 범위 있는 enum을 선호하라
(1) typedef는 템플릿화를 지원하지 X, 별칭 선언은 지원
-typedef로 템플릿화를 흉내내려면 불편하게 struct 안에 내포된 typedef들을 활용하는 편법 필요. 반면 별칭 템플릿은 훨씬 더 간단하고 직접적으로 표현
(2) 별칭 템플릿에서는 "::type" 접미어를 붙일 필요가 없다. 템플릿 안에서 typedef를 지정할 때에는 "typename" 접두사를 붙어야 하는 경우가 많다.
(3) C++14는 C++11의 모든 타입 특성 변환에 대한 별칭 템플릿들을 제공한다.
-C++11에 있는 std::변환<T>::type 형태의 각 형식 특징에 대해, C++에서는 std::변환_t 형태의 별칭 템플릿
10. 범위 없는 enum보다 범위 있는 enum을 선호하라
<범위 있는 enum 특징>
-범위있는 enum과 범위없는 enum 모두 바탕 형식 지정을 지원.
->범위있는 enum의 기본 바탕 형식은 int. 범위없는 enum에는 기본 바탕 형식 X
-열거자들의 형식이 훨씬 강력하게 적용. 즉, 범위 있는 enum의 열거자는 암묵적으로 다른 형식으로 변환되지 X
-범위 있는 enum은 전방 선언(forward declaration)이 가능. 범위없는 enum은 해당 선언에 바탕 형식을 지정하는 경우에만 전방 선언이 가능.
11. 정의되지 않은 비공개 함수보다 삭제된 함수를 선호하라
-delete 를 붙인 함수 -> 삭제된 함수(deleted function)라 호칭
-삭제된 함수는 private이 아니라 public으로 선언하는 것이 관례
-비멤버 함수와 템플릿 인스턴스를 비롯한 그 어떤 함수도 삭제 가능
12. 재정의 함수들을 override로 선언하라
<재정의가 일어나기 위해 만족해야 하는 필수 조건>
- 기반 클래스 함수가 반드시 가상 함수이어야 한다.
- 기반 함수와 파생 함수의 이름이 반드시 동일해야 한다(단, 소멸자는 예외).
- 기반 함수와 파생 함수의 매개변수 형식들이 반드시 동일해야 한다.
- 기반 함수와 파생 함수의 const성이 반드시 동일해야 한다.
- 기반 함수와 파생 함수의 반환 형식과 예외 명세가 반드시 호환되어야 한다.
- 멤버 함수들의 참조 한정사(reference qualifier)들이 반드시 동일해야 한다. (멤버 함수 참조 한정사: 멤버 함수를 좌측값에만 또는 우측값에만 사용할 수 있게 제한하는 기능)
13. iterator보다 const_iterator를 선호하라
-iterator보다 const_iterator를 선호하라.
-최대한 일반적인 코드에서는 begin, end, rbegin등의 비멤버 버전들을 해당 멤버 함수들보다 선호하라.
14. 예외를 방출하지 않을 함수는 noexcept로 선언하라
함수 선언 시 그 함수가 예외를 방출하지 않을 것임을 명시할 때에는 noexcept라는 키워드를 사용
<noexcept 함수 특징>
-비noexcept 함수보다 최적화의 여지가 큼
-이동 연산들과 swap, 메모리 해제 함수들, 그리고 소멸자들에 특히나 유용
-함수의 구현이 예외를 방출하지 않는다는 성질을 오랫동안 유지할 결심이 선 경우에만 함수를 noexcept로 선언
-noexcept는 함수의 인터페이스의 일부. 이는 호출자가 noexcept 여부에 의존할 수 있음을 의미
15. 가능하면 항상 constexpr을 사용하라
- 컴파일 시점 상수를 요구하는 문맥에 constexpr 함수를 사용할 수 있다. 그런 문맥에서, 만일 constexpr 함수에 넘겨주는 인수의 값이 컴파일 시점에서 알려진다면, 함수의 결과는 컴파일 도중에 계산된다. 인수의 값이 컴파일 시점에서 알려지지 않는다면, 코드의 컴파일이 거부된다.
- 컴파일 시점에서 알려지지 않는 하나 이상의 값들로 constexpr 함수를 호출하면 함수는 보통의 함수처럼 작동한다. 즉, 그 결과는 실행시점에서 계산된다. 이는 같은 연산을 수행하는 함수를 두 버전, 즉 컴파일 시점 상수를 위한 버전과 다른 모든 값을 위한 버전으로 나누어서 구현할 필요가 없음을 뜻한다. 그냥 하나의 constexpr 함수를 두 가지 용도로 사용하면 된다.
- constexpr 객체는 const이며, 컴파일 도중에 알려지는 값들로 초기화된다.
- constexpr 함수는 그 값이 컴파일 도중에 알려지는 인수들로 호출하는 경우에는 컴파일 시점 결과를 산출한다.
- constexpr 객체나 함수는 비constexpr 객체나 함수보다 광범위한 문맥에서 사용할 수 있다.
- constexpr은 객체나 함수의 인터페이스의 일부이다.
16. const 멤버 함수를 스레드에 안전하게 작성하라.-
-동시적 문맥에서 쓰이지 않을 것이 확실한 경우가 아니라면, const 멤버함수는 스레드에 안전하게 작성하라.
-std::atomic 변수는 뮤텍스에 비해 성능상이 이점이 있지만, 하나의 변수 또는 메모리 장소를 다룰 때에만 적합하다.
17. 특수 멤버 함수들의 자동 작성 조건을 숙지하라
클래스에 대한 이동 연산들은 다음 세 조건이 모두 만족되고 필요할 때 작성됨.
- 클래스에 그 어떤 복사 연산도 선언되어 있지 않다.
- 클래스에 그 어떤 이동 연산도 선언되어 있지 않다.
- 클래스에 소멸자가 선언되어 있지 않다.
*컴파일러가 스스로 작성할 수 있는 멤버 함수들, 즉 기본 생성자와 소멸자, 복사 연산들, 이동 연산들을 가리켜 특수 멤버 함수라고 부른다.
'modern effective c++' 카테고리의 다른 글
effective modern c++ chap.4 (0) | 2020.03.02 |
---|---|
effective modern c++ chap.2 (0) | 2020.02.17 |