본문 바로가기
modern effective c++

effective modern c++ chap.3

by 몰라몰라개복치 2020. 2. 24.

7. 객체 생성시 괄호(())와 중괄호({})를 구분하라

기존의 변수 초기화 방법에, 중괄호 초기화 방법을 더해 총 4가지의 방법으로 변수를 초기화

변수를 초기화하는 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)들이 반드시 동일해야 한다. (멤버 함수 참조 한정사: 멤버 함수를 좌측값에만 또는 우측값에만 사용할 수 있게 제한하는 기능)

override를 사용하고 제대로 컴파일되는 코드 예시

 

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