전체 글 131

Effective Modern C++ #34 std::bind 보다 람다를 선호하라

34. std::bind 보다 람다를 선호하라std::bind 는 C++98 의 std::bind1st, std::bind2nd 를 계승했으며 2005년 표준 라이브러리의 일부이기도 했다.하지만 C++14 이상부터는 람다가 std::bind 보다 우월한 선택이므로 람다를 사용하자.*C++11 에서는 특정 케이스에서만 std::bind 사용이 용인된다. std::bind 와 비교했을 때, 람다의 장점은 다음과 같다.1. 가독성람다 예시)void setAlarm(Time t, Sound s, Duration d);// 한시간 후부터 지정된 소리를 30초간 재생auto setSoundL = [](Sound s) { using namespace std::chrono; using namespace std::lit..

dev/C++ 2025.06.30

Effective Modern C++ #33 std::forward 를 통해서 전달할 auto&& 매개변수에는 decltype 을 사용하라

33. std::forward 를 통해서 전달할 auto&& 매개변수에는 decltype 을 사용하라C++14 에서 가장 exciting 한 기능은 매개변수에 auto를 사용할 수 있는 general lambda 기능이다.람다 클로저 클래스의 operator 를 템플릿 함수로 만들어서 임의로 구현할 수 있다.예시)auto f = [](auto x){ return normalize(x); };// 위 람다함수 auto 구현하는 법class 컴파일러가_만든_이름 { public: template auto operator()(T x) const { return normalize(x); } ...};이제 위 케이스에서 x 가 l-value 또는 r-value 인자로 전달된다고 가..

dev/C++ 2025.06.30

Effective Modern C++ #32 객체를 클로저 안으로 이동하려면 초기화 캡쳐 (갈무리)를 사용하라

32. 객체를 클로저 안으로 이동하려면 초기화 캡쳐 (갈무리)를 사용하라값 캡쳐, 참조 캡쳐 모두 사용하기 애매한 경우가 있다.이동 전용 객체 (ex. std::unique_ptr )를 클로저 안으로 들여올 때가 그렇다.C++11 에서는 방법이 없지만. C++14 에서는 객체를 클로저 안에 이동하는 기능을 제공한다.Init Capture (초기화 캡쳐) 방식이 있는데 기본 캡쳐 모드 외에는 C++11 캡쳐 모드에서 지원하는 기능 전부 지원한다.초기화 캡쳐는 다음과 같은 항목 지정이 가능하다.람다로부터 생성되는 클로저 클래스의 자료 멤버 이름해당 자료 멤버 초기화 표현식예시)auto pw = std::make_unique();...auto func = [pw = std::move(pw)] { return ..

dev/C++ 2025.06.30

Effective Modern C++ #31 기본 Capture mode를 피해라

람다 표현식C++의 면모를 크게 바꾸는 새로운 기능이다.사실 람다가 할 수 있는 모든 일은 람다를 사용하지 않고도 구현할 수 있다.하지만 함수 객체 만들기가 쉬워지므로 C++ 개발에 큰 영향을 준다. 람다 표현식이 없다면 std::find_if, std::remove_if, std::count_if 등은 조건자(predicate)와 사용만 가능하다.*ex. std::find_if(v.begin(), v.end(), isEven); 에서 3번째 인자에 들어가는 것이 predicate (함수 포인터, 함수 객체 등)커스텀 가능한 비교 연산(std::sort, std::nth_element, std::lower_bound 등)도 마찬가지이다. 람다 표현식의 예시)std::find_if(container.beg..

dev/C++ 2025.06.30

Effective Modern C++ #30 완벽 전달이 실패하는 경우들을 잘 알아두라

30. 완벽 전달이 실패하는 경우들을 잘 알아두라Perfect Forwarding 은 C++11 의 주요 기능 중 하나이다.한 함수가 다른 함수에 자신의 인자를 전달할 때, 다른 함수에 받은 것과 동일한 객체를 전달하는 방법이다.( ex. 값 매개변수를 사용하는 경우 복사본을 전달하므로 동일한 객체가 아니다 ) 객체 전달 외에도 l-value/ r-value 여부, const, volatile 여부 등 전달되는 객체의 특징도 포함한다.따라서 보편 참조 매개변수를 사용해야한다.(#23에서 다룬 내용) 보편 참조 매개변수만 l-value, r-value 정보를 저장하기 때문이다.예시)templatevoid fwd(T&& param) { f(std::forward(param));}위와 같이 완벽 전달은 특정 ..

dev/C++ 2025.06.30

Effective Modern C++ #29 이동 연산이 존재하지 않고, 저렴하지 않고, 적용되지 않는다고 가정하라.

29. 이동 연산이 존재하지 않고, 저렴하지 않고, 적용되지 않는다고 가정하라.move semantics (이동 의미론)는 C++11 의 가장 주요한 기능이다.컴파일러는 비싼 복사 연산을 비교적 저렴한 이동 연산으로 대체할 수 있다. (가능하면 그렇게 해야한다)또한 C++98 코드 기반을 C++11 준수하는 컴파일러와 표준 라이브러리로 컴파일하면, 소프트웨어가 자동으로 더 빠르게 실행된다. (컨테이너 등 내부적 로직에서 이동 연산이 사용되므로 자동 개선) 개발자들은 이동 연산에 열광하나, 과장된 부분도 분명 존재한다.이번 시간에는 이동 의미론에 대해 근거 있는 기대를 가질 수 있게 자세히 알아보자. move semantics 를 지원하지 않는 형식도 다수 존재한다.특수 멤버 함수 자동 생성 조건에 맞지 ..

dev/C++ 2025.06.28

Effective Modern C++ #28 참조 축약을 숙지하라

28. 참조 축약을 숙지하라보편 참조 생성자에서 인자로 보편 참조 매개변수를 초기화할 때, T (템플릿 매개변수) 에는 인자의 정보가 부호화 되어 있다.(l-value/r-value 여부) 예시)templatevoid func(T&& param);위 케이스에서 T 에는 param 에 전달된 정보가 존재한다. 예시)Widget w; // l-valueWidget widgetFactory(); // r-valuefunc(w); // l-value 전달, T = Widget&func(widgetFactory()); // r-value 전달, T = Widget위 예시에서 각각 func 함수 인자로 l-value/r-value 가 전달된다.l-value/r-value 에 따라 T에 연역되는 형식이 다르다. C+..

dev/C++ 2025.06.25

Effective Modern C++ #27 보편참조 에 대한 중복적재(overload) 대신 사용할 수 있는 기법들을 알아두라

27. 보편참조에 대한 중복적재(overload) 대신 사용할 수 있는 기법들을 알아두라동일한 이름의 보편 참조 함수와 overload 함수를 같이 사용했을 때, 문제가 될 수 있다는 점을 이전 시간에 배웠다.예상보다 더 많은 호출자가 보편 참조 함수 로직을 타게 된다. (더 부합하기 때문)오버로드 포기간단하게 overload 를 포기하고 함수 이름을 나누면 된다. (ex. logAndAdd -> logAndAddName, logAndAddNameIdx)유지보수에 복잡성이 커지는 단점이 있다.또한 자동으로 작성되는 클래스 생성자로 인한 overload 는 대처가 불가능하다.생성자 이름은 클래스 이름으로 고정되기 때문이다. const T& 매개변수 사용보편 참조 대신 l-value 에 대한 참조 매개변수를..

dev/C++ 2025.06.25

Effective Modern C++ #26 보편 참조에 대한 중복적재(overload)를 피하라

26. 보편 참조에 대한 중복적재(overload)를 피하라예시)#include#include#includestd::multiset names;void addName(const std::string& name) { names.emplace(name);}int main() { std::string petName("Darla"); addName(petName); // case 1: l-value std::string 넘김 addName(std::string("Persephone")); // case 2: r-value std::string 넘김 addName("Patty Dog"); // case 3: std::string 리터럴 넘김}위 코드는 비효율적이다.일단 함수 매개변..

dev/C++ 2025.06.23

Effective Modern C++ #25 오른값 참조 (r-value ref)에는 std::move 를, 보편 참조에는 std::forward를 사용하라

25. 오른값 참조 (r-value ref)에는 std::move 를, 보편 참조에는 std::forward를 사용하라#23 std::move와 std::forward 를 숙지하라.#24 보편 참조와 오른값 참조(r-value ref)를 구별하라. 앞서 배운 #23, #24 의 내용들이 합쳐진다. r-value 참조의 경우, r-value 성질을 활용할 수 있게 r-value 로 캐스팅해주는 std::move 를 사용한다.보편참조의 경우, r-value 로 초기화되는 경우만 r-value 로 캐스팅해주는 std::forward 를 사용한다. 이를 따르지 않는 것은 권장되지 않는다.r-value 참조에 std::forward 사용작성해야하는 형식이 더 많으며 실수의 여지가 존재함보편 참조에 std::mov..

dev/C++ 2025.06.22