본문 바로가기

전체 글44

24. 보편 참조(universal reference)와 우측값 참조를 구별하라. 1. 함수 템플릿 매개 변수의 타입이 T&& 형태이고 T가 추론된다면, 또는 객체를 auto&& 로 선언한다면, 그 매개변수나 객체는 보편 참조이다. 보편 참조는 우측값, 좌측값은 물론 const 객체, 비 const 객체, volatile 객체, 비 volatile 객체, 심지어 const 이자 volatile 인 객체에도 묶을 수 있다. 2. 타입 선언의 형태가 정확히 타입 &&가 아니면, 또는 타입 추론이 일어나지 않으면, 타입 &&은 우측값 참조를 뜻한다. void f(Widget&& param); // 우측값 참조 Widget&& var1 = Widget(); // 우측값 참조 auto&& var2 = var1; // 우측값 참조 아님 template void f(std::vector&& par.. 2021. 9. 5.
23. std::move와 std::forward를 숙지하라. - std::move는 우측값으로의 무조건 캐스팅을 수행한다. std::move 자체는 아무것도 이동하지 않는다. C++11의 std::move를 구현한 예를 보자. 표준의 세부사항들을 완전히 준수하는 구현은 아니지만, 그런 완전한 구현에 아주 가깝다 template typename std::remove_reference::type&& move(T&& param) { using ReturnType = typename std::remove_reference::type&&; return static_cast(param); } 항목 28에서 설명하듯이, 타입 T가 하필 좌측값 참조이면 T&&는 좌측값 참조가 된다. 이를 방지하기 위해, 이 구현은 T에 타입 특성 (항목 9 참고) std::remove_refe.. 2021. 3. 13.
22. Pimpl 관용구를 사용할 때에는 특수 멤버 함수들을 구현파일에서 정의하라. - Pimpl 관용구는 클래스 구현과 클래스 클라이언트 사이의 컴파일 의존성을 줄임으로써 빌드 시간을 감소한다. 예를 들어 다음과 같은 모습의 Widget 클래스가 있다고 하자. // "Widget.h" 헤더 파일 안에서 class Widget { public: Widget(void); private: std::string name; std::vector data; Gadget g1, g2, g3; // Gadget은 어떤 사용자 정의 타입 }; Widget의 데이터 멤버들이 std::string, std::vector, Gadget 타입이므로, Widget을 컴파일하려면 그 타입들의 헤더가 있어야 한다. 즉, Widget의 클라이언트는 반드시 #include를 이용해서 , , gadget.h 를 포함해.. 2021. 3. 13.
21. new를 직접 사용하는 것보다 std::make_unique와 std::make_shared를 선호하라. - new의 직접 사용에 비해, make 함수를 사용하면 소스 코드 중복의 여지가 없어지고, 예외 안전성이 향상되고, std::make_shared와 std::allocate_shared의 경우 더 작고 빠른 코드가 산출된다. std::make_shared는 C++11의 일부이지만, std::make_unique는 C++14에서야 표준 라이브러리에 포함되었다. 하지만 C++11 환경에서 make_unique와 같은 일을 하는 함수 템플릿을 만드는 것은 어렵지 않다. template std::unique_ptr make_unique(Ts&&... params) { return std::unique_ptr(new T(std::forward(params)...)); } 완전한 기능을 갖춘 make_unique.. 2021. 3. 12.