2025/07 8

Effective Modern C++ #42 삽입 대신 생성 삽입을 고려하라.

42. 삽입(insertion) 대신 생성 삽입 (emplacement)을 고려하라.컨테이너에 항목을 추가할 때, 항상 템플릿에 딱 맞는 항목을 전달하지 않아도 된다.예시)std::vector vs;vs.push_back("xyzzy"); // 문자열 리터럴 추가위 예시에서 컨테이너는 std::string 을 담는다.하지만 push_back 으로 넘겨주는 것은 문자열 리터럴이다. 참고로 push_back 은 다음과 같이, overload 함수로 구현된다.template >class vector { public: void push_back(const T& x); // l-value void push_back(T&& x); // r-value} 컴파일러는 문자열 리터럴로부터 임시 std::str..

dev/C++ 2025.07.09

Effective Modern C++ #41 이동이 저렴하고 항상 복사되는 복사 가능 매개변수에 대해서는 값 전달을 고려하라

다듬기값 전달, 생성 삽입에 대해 알아볼 것이다.이들의 사용을 고려하라는 조언이며, 어떤 상황에서 사용이 적절한지 알아보자.41. 이동이 저렴하고 항상 복사되는 복사 가능 매개변수에 대해서는 값 전달을 고려하라함수가 있을 때, l-value 인자는 복사하고, r-value 인자는 이동하는 것이 적절하다.이를 구현할 수 있는 여러가지 방법들을 알아보자. overload 함수예시)class Widget { public: void addName(const std::string& newNames) { names.push_back(newNames); } void addName(std::string&& newNames) { names.push_back(std::move(newNames)); } pri..

dev/C++ 2025.07.08

Effective Modern C++ #40 동시성에는 std::atomic 을 사용하고, volatile 은 특별한 메모리에 사용하라

40. 동시성에는 std::atomic 을 사용하고, volatile 은 특별한 메모리에 사용하라개발자가 volatile 과 혼동하는 C++ 기능은 std::atomic 이다.std::atomic 이 생성하는 템플릿 인스턴스는 다른 스레드가 원자적으로 인식하는 연산을 제공한다.따라서 std::atomic 객체에 대한 연산은, 뮤텍스로 보호되는 영역 안에서 수행되는 것처럼 작동한다.*뮤텍스보다 좀 더 효율적인 기계어 명령으로 구현됨 std::atomic예시)std::atomic ai(0);ai = 10;std::cout 이 예시 코드가 실행되는 동안, 다른 스레드에서 ai 를 읽으면 0, 10, 11 의 값만 확인할 수 있다. 위 코드에서 주목할 부분은 두가지이다.1.`std::cout 하지만 operat..

dev/C++ 2025.07.07

Effective Modern C++ #39 단발성 사건 통신에는 void 미래 객체를 고려하라

39. 단발성 사건 통신에는 void 미래 객체를 고려하라event 를 감지해서 작업을 진행해야하는 비동기 스레드에 대해 알아보자.이러한 용도로 스레드를 사용할 때, 스레드간 통신 방법은 다양한다. 스레드간 통신을 처리하는 방법 중 가장 좋은 방법이 뭘까?조건 변수 (condition variable)두 가지 용도의 스레드가 존재한다.검출 과제사건이 발생하면 조건 변수 notify반응 과제조건 변수 notify 되는 순간을 기다림검출 과제 예시)...cv.notify_one(); // 반응 과제에 알림반응 과제 예시) ...{ std::unique_lock lk(m); // 뮤텍스 잠금 cv.wait(lk); // notify 기다림}위 예시에서 (반응 과제의 경우) 조건 변수에 대해 wait 을 호출하..

dev/C++ 2025.07.06

Effective Modern C++ #38 스레드 핸들 소멸자들의 다양한 행동 방식을 주의하라

38. 스레드 핸들 소멸자들의 다양한 행동 방식을 주의하라joinable std::thread 를 파괴하면 프로그램이 종료된다.하지만 미래 객체의 소멸자는 언제는 암묵적 join, 언제는 암묵적 detach 의 동작을 한다.이러한 스레드 핸들 소멸자의 동작 확인을 위해, 확인해야하는 상태가 있다. 위 그림처럼 미래 객체는 호출자에서, 피호출자 결과를 받을 수 있는 채널이다. ( 통신 채널의 한쪽 끝 )그렇다면 피호출자 결과는 어디에 저장될까?후보 1) 피호출자호출자가 미래 객체.get 호출하기 전에 피호출자가 종료될수 있음따라서 피호출자에 저장 불가능후보 2) 호출자 미래 객체std::future 로 std::shared_future 를 생성하면 미래객체 결과의 소유권이 이전됨원본 호출자의 미래 객체가 ..

dev/C++ 2025.07.05

Effective Modern C++ #37 std::thread 들을 모든 경로에서 unjoinable (합류 불가능)하게 만들어라

37. std::thread 들을 모든 경로에서 unjoinable (합류 불가능)하게 만들어라std::thread 객체는 joinable 또는 unjoinable 상태이다.unjoinable std::thread 객체는 다음과 같다.기본 생성 std::thread이동된 후 남겨진 std::threadjoin 에 의해 합류된 std::threaddetach 에 의해 탈착된 std::thread합류 가능 (joinable) 한 스레드의 소멸자가 불리는 경우, 프로그램이 종료 (terminate)된다.프로그램이 종료되는 이유는, 그 이외의 동작보다는 더 나은 선택이기 때문이다.암묵적 joinstd::thread 소멸자가 background 비동기 thread를 기다리는 것추적하기 어려운 성능 이상이 나타날 ..

dev/C++ 2025.07.03

Effective Modern C++ #36 비동기성이 필수일 때에는 std::launch::async 를 지정하라

36. 비동기성이 필수일 때에는 std::launch::async 를 지정하라일반적으로 std::async 를 호출해서 함수를 실행하는 것은 비동기적으로 실행하겠다는 의도가 존재한다.하지만 항상 그러한 의미로 사용되지 않는다.std::async 호출은 함수를 어떤 launch policy (시동 방침) 에 따라 실행한다는 더 일반적인 의미를 가진다. 함수 f 를 std::async 통해 실행할 때, 다음 launch policy을 인자로 사용할 수 있다.std::launch::asyncf 는 비동기적으로 (다른 스레드에서) 실행됨std::launch::deferredstd::async 가 리턴한 std::future 객체로 get/wait 호출되어야만 f 실행 가능f 의 실행은 그러한 호출까지 지연됨(d..

dev/C++ 2025.07.02

Effective Modern C++ #35 스레드 기반 프로그래밍보다 과제 기반 프로그래밍을 선호하라

동시성 APIC++11 의 큰 성과는 동시성을 언어와 표준 라이브러리에 도입한 것이다.다른 스레드 기능에 비해 제약도 큰데, C++의 동시성 지원의 상당 부분이 컴파일러 작성자에 대한 제약의 형태이기 때문이다.표준 라이브러리에서 future 객체를 위한 템플릿은 2개이며, 해당 장에서는 둘의 구분이 중요하지 않은 경우 미래 객체라고 통칭한다.( std::future, std::shared_future )35. 스레드 기반 프로그래밍보다 과제 기반 프로그래밍을 선호하라비동기적 실행의 방법은 크게 두가지가 있다.thread-based 프로그래밍std::thread 객체 생성해서 그 객체에서 함수 실행한다.예시)int doAsyncWork();std::thread t(doAsyncWork); task-base..

dev/C++ 2025.07.02