반응형

전체 글 310

[CH4] Item22. When using the Pimpl Idiom, define special member functions in the implementation file.

Item 22는 'Pimpl 관용구를 사용할 때, 특수 멤버 함수들을 구현 파일에 정의하라'는 내용이다. C++ 개발에서 흔하게 사용되는 Pimpl(Pointer to Implementation) 관용구와 스마트 포인터가 만났을 때 발생하는 컴파일 에러에 대한 내용을 다루는 장이다. 먼저 한 줄로 요약하면 다음과 같다.Pimpl을 쓸 때, std::unique_ptr 를 사용한다면, 소멸자와 이동 연산자들을 헤더가 아닌 구현파일(.cpp)에 명시적으로 정의하라 --- 과도한 빌드 시간과 싸워본 적이 있다면, Pimpl("pointer to implementation", 구현을 위한 포인터) 관용구에 익숙할 것이다. 이것은 클래스의 데이터 멤버들을 구현 클래스(또는 구조체)를 가리키는 포인터로 대체하고, ..

[CH4] Item21. Prefer std::make_unique and std::make_shared to direct use of new.

Item 21은 new를 직접 사용하는 것보다 make_unique와 make_shared를 선호하라는 내용이다. C++11에선 make_shared만 있었지만, C++14에서 make_unique가 추가되었고, 이제 거의 모든 상황에서 new를 직접 호출할 필요가 없어지게 된 이야기이다. --- make_shared는 C++11의 일부이지만, make_unique는 C++14에 이르러서야 표준 라이브러리에 포함되었다.기본적인 버전의 make_unique를 직접 작성하는 것은 쉬운데, 아래의 코드를 보자templatestd::unique_ptr make_unique(Ts&&... params){ return std::unique_ptr(new T(std::forward(params)...));}make..

[CH4] Item20. Use std::weak_ptr for std::shared_ptr like pointers that can dangle.

Item 20은 '대상을 잃을 수 있는 스마트 포인터에는 weak_ptr을 사용해라'이다. --- shared_ptr처럼 작동하면서도 가리키는 자원의 공유 소유권에는 참여하지 않는 스마트포인터가 있으면 편리할 때가 있다.다시 말해, 객체의 참조 횟수(reference count)에는 영향을 주지 않으면서, shared_ptr와 같은 포인터가 있다.이런 종류의 스마트 포인터는 shared_ptr가 겪지 않는 문제, 즉 가리키는 대상이 이미 파괴되었을 가능성에 대처해야만 한다. 자신이 가리키는 대상을 잃었을 때(dangling), 즉, 가리키기로 되어 있는 객체가 더 이상 존재하지 않을 때를 추적함으로써 이 문제를 해결할 것이며, 그것이 정확히 weak_ptr이 하는 일이다. weak_ptr가 어떻게 유용할..

[CH4] Item19. Use std::shared_ptr for shared-ownership resource management.

Item 19는 '공동 소유 자원의 관리에는 std::shared_ptr'을 사용하라'이다.unique_ptr은 소유권이 명확할 때 최고지만, 현실적으로는 하나의 객체가 여러 곳에서 참조되어 사용될 때가 많다.이럴 때, 참조 횟수(Reference Counting)를 기반으로 하는 shared_ptr을 사용하면 좋다. --- Garbage Collection은 메모리를 기계가 관리하기에 확실히 편리하다. 아무리 자원의 해제가 비결정적(nondeterministic)이더라도 C++에서 수동으로 수명을 관리하는 것은 어려운 게 사실이다. std::shared_ptr는 Garbage Collection을 사용하는 곳의 자동 수명 관리와 자원 해제 시점의 예측 가능성을 모두 가진 C++11의 키워드이다.std:..

[CH4] Item18. Use std::unique_ptr for exclusive-ownership resource management.

Item18은 독점 소유 자원의 관리에는 std::unique_ptr를 사용해라 는 주제이다. --- unique_ptr는 생 포인터(Raw Pointer)와 크기가 같다고 가정하는게 합리적이며, 역참조(dereferencing)를 포함한 대부분의 연산에서 정확히 동일한 명령어가 실행된다. 이는 메모리와 CPU 사이클이 부족한 상황에서도 이를 사용할 수 있음을 의미한다. 만약 생 포인터가 충분히 작고 빠르다면, unique_ptr 역시 그럴 것이다. unique_ptr는 독점적 소유권 의미론(exclusive ownership semantics)을 구현한다.null이 아닌 unique_ptr는 항상 그것이 가리키는 대상을 소유한다. unique_ptr를 이동(move)하는 것은 소유권을 원본 포인터에서 ..

[CH.4] Smart Pointers

스마트 포인터에 관한 내용을 이야기하는 4장이다. 생포인터(Raw Pointer)를 사용하기 힘든 이유1. 가리키는 대상의 모호함- 포인터 선언만으로는 단 하나의 객체를 가리키는지, 아니면 배열 전체를 가리키는지 알 수 없음2. 소유권의 불분명함- 사용을 마친 후 가리키는 대상을 파괴(destroy)해야 하는지 알 수 없음. - 포인터가 그 대상의 '소유권'을 가졌는지 여부는 선언부만으로는 알 수 없음3. 파괴 방법의 불확실성- 파괴해야 한다면 어떻게 해야하는지 명확하지 않음- delete를 써야 하는지, 별도의 전용 파괴 함수를 호출해야 하는지 등4. delete와 delete[]- 만약 delete를 쓰는게 맞더라도, 단일 객체용(delete)을 써야 할지, 배열용(delete[])을 써야할지 모름..

[CH3] Item17. Understand special member function generation.

Item 17. 특수 멤버 함수들의 자동 생성 규칙을 숙지하라는 내용이다. --- 특수 멤버 함수(special member functions)란, C++이 스스로 생성할 의사가 있는 함수들을 말한다.C++98에는 4개의 특수 멤버 함수가 있는데, 기본 생성자, 소멸자, 복사 생성자, 복사 대입 연산자이다. 이 함수들은 필요할 때만 생성된다. 즉, 클래스에 명시적으로 선언되지 않았더라도 어떤 코드에서 그 함수를 사용할 때 생성된다는 의미이다.- 기본 생성자 : 클래스가 그 어떤 생성자도 선언하지 않았을 때만 생성. (이는 사용자가 생성자 인자가 반드시 필요하다고 명시한 클래스에 대해, 컴파일러가 멋대로 기본 생성자를 만드는 것을 방지하기 위함.)- 특성 : 생성된 특수 멤버 함수들은 암시적으로 publi..

[C++] 이동 전용 클래스(Move-only Class)

복사는 불가능하고 오직 이동(move)만 가능한 클래스.대표적인 예시로 std::unique_ptr이나 std::thread 가 그것이다. 이동전용 클래스를 만드는 법은, 복사 생성자와 복사 할당 연산자를 delete 키워드로 명시적 삭제하고, 이동 생성자와 이동 할당 연산자만 정의하면 된다.코드 예시는 아래와 같다.class MoveOnly {public: MoveOnly() = default; // 1. 복사 생성 및 복사 할당 금지 MoveOnly(const MoveOnly&) = delete; MoveOnly& operator=(const MoveOnly&) = delete; // 2. 이동 생성 및 이동 할당 허용 MoveOnly(MoveOnly&& other) ..

개발 관련 2026.03.29

[CH3] Item16. Make const member functions thread safe.

Item16은 'const 멤버 함수는 스레드 안전하게 작성해라' 라는 이야기다. const는 값을 바꾸지 않는다는 생각으로 여러 스레드에서 동시에 접근하도록 하면 안된다는 내용이다. --- 수학적 영역에서 작업한다면 다항식(polynomial)을 나타내는 클래스를 갖는 것이 판리할 것이다.그리고 이 클래스 내에 다항식의 해(root), 즉 다항식의 값이 0이 되는 값들을 계산하는 함수를 두는 것 또한 아마도 유용할거다.그리고 이 함수는 다항식을 수정하지 않으므로 const로 선언하는게 올바른 방향일 것이다.이런 방향으로 코드를 작성한다면 아래와 같을 것이다.class Polynomial {public: using RootsType = // 해의 값들을 보유하는 데이터 구조 ..

[CH3] Item15. Use constexpr whenever possible.

Item 15는 '가능하면 언제나 constexpr을 사용하라'는 주제이다. constexpr은 혼란스러운 단어이다.객체(변수)에 붙으면 기본적으로 강력해진 const 같은 느낌이지만, 함수에 붙을때는 의미가 완전히 달라진다. 개념적으로 constexpr은 값이 상수일 뿐만 아니라, 컴파일 도중에 이미 그 값을 알고 있음을 나타낸다.그리고 constexpr 함수의 결과가 항상 const인 것도 아니고 그 값이 반드시 컴파일 타임에 결정되지 않는다. 이것이 constexpr의 장점이다. constexpr가 붙은 객체는, 실제로 const이며 실제로 컴파일 타임에 결정된 값을 가진다. 그리고 컴파일 도중에 결정된 값은 매우 특별한 대우(Privileged)를 받는다.이런 값들은 읽기전용 메모리(ROM)에 저..

반응형