본문 바로가기

SW/C++

C++ : shared_ptr 와 weak_ptr : 개념, 차이, 활용법, 예제, 구현 std::shared_ptr 강한 참조 기반입니다. 강한 참조 카운트를 늘려줍니다. 직접적으로 사용할 수 있습니다. 원시 포인터가 확실히 존재하기 때문입니다. std::weak_ptr 약한 참조 기반입니다. 약한 참조 카운트를 늘려줍니다. 직접적으로 사용할 수 없습니다. lock을 써서 std::shared_ptr가 여전히 존재하는 지 확인해야 합니다. 예제 #pragma once #include #include #include #include #include "MyVector2D.h" using namespace std; namespace samples { class SimpleCache { public: SimpleCache() = default; ~SimpleCache() = default; voi..
C++ : weak_ptr : 약한 참조 개념, 사용법, 예제, 구현 약한 참조 약한 참조는 원시 포인터 해제에 영향을 끼치지 않습니다. 약한 참조 카운트는 약한 참조의 수를 저장하는 데 사용됩니다. 약한 참조로 참조되는 개체는 강한 참조 카운트가 0이 될 때 소멸됩니다. 순환 참조 문제의 해결책입니다. #include #include "Persion.h" int main() { std::shared_ptr owner = std::make_shared("pp"); std::weak_ptr weakOwner = owner; return 0; } 약한 포인터로 공유 포인터 만들기 #include #include "Persion.h" int main() { std::shared_ptr owner = std::make_shared("pp"); std::weak_ptr weakOw..
C++ : shared_ptr : 개념, 예제, 사용법, 구현 std::shared_ptr #include #include"Vector.h" int main() { std::shared_ptr vector = std::maked_shared(10.f, 30.f); // ... } 두개의 포인터를 소유합니다. 데이터를 가리키는 포인터와 제어 블록을 가리키는 포인터입니다. std::unique_ptr와 달리, 포인터를 다른 std::shared_ptr와 공유할 수 있습니다. 참조 카운팅 기반이라 할 수 있습니다. 원시 포인터는 어떠한 std::shared_ptr에게도 참조되지 않을 때 소멸됩니다. 포인터 재설정하기 std::shared_ptr vector = std::maked_shared(10.f, 30.f); std::shared_ptr copiedVector = ..
C++ : 자동 메모리 관리, 가비지 컬렉션, 참조 카운트 : 개념, 관계, 장단점 자동 메모리 관리 std::shared_ptr를 배우기 전에, 자동 메모리 관리에 관해 알아야 합니다. 주로 쓰는 두가지 기법이 있었습니다. 첫번째는 가비지 컬렉션이고, 두번째는 참조 카운팅이 있습니다. 가비지컬렉션은 Java와 C#에서 활용되고 있으며, 참조 카운팅은 Swift와 오브젝트 C에서 지원됩니다. 가비지 컬렉션 보통 트레이싱 가비지 컬렉션을 의미합니다. 메모리 누수를 막으려는 시도에서 나오게 되었습니다. 주기적으로 컬렉션을 실행합니다. 충분한 여유 메모리가 없을 때 컬렉션이 실행됩니다. 스케쥴에 따라 또는 수동으로도 실행 가능합니다. 매 주기마다 GC는 루트를 확인합니다. 즉, 전역 변수, 스택, 레지스터들을 확인합니다. 힙에 있는 개체에 루트를 통해 접근할 수 있는 지 판단합니다. 접근할 ..
C++ : unique_ptr : 배스트 프렉티스, 기본 예제, 활용 방법, 동작 방식 std::unique_ptr 포인터 대신 아주 많이 활용되고 있습니다. 직접 메모리 관리하는 것 만큼 빠릅니다. Resource Acquisition is initialization 원칙에 잘 들어맞습니다. 자원 할당은 개체의 수명과 관련되어 있습니다. 생성자에서 new를 하고 소멸자에서 delete를 해주어야하는데 유니크 포인터 멤버 변수가 알아서 동작하여 줍니다. 따라서, 실수하기 어려우며, 다양한 곳에서 활용하여도 좋습니다. 예제 #include #include #include "UsingUniquePointersExample.h" #include "MyVector.h" using namespace std; namespace samples { void UsingUniquePointersExample..
C++ : unique_ptr : reset, get, release, move, 복사 : 개념, 예제 reset() int main() { std::unique_ptr vector = std::make_unique(10.f, 30.f); vector.reset(new Vector(20.f, 40.f)); vector.reset(); } 이거 말고 nullptr를 써야할까? vector.reset(); vecotr = nullptr; 두 코드의 의미는 같습니다. nullptr가 reset() 보다 가독성이 더 좋습니다. reset()은 vector가 원시 포인터가 아님을 분명하게 보여줍니다. 따라서, 취향에 맞게 구현하여도 무방하다고 합니다. reset()은 결국 포인터를 교체하는 것을 의미합니다. std::unique_ptr가 재설정 될 떄, 소유하고 있던 원시 포인터는 자동으로 소멸됩니다. get() ..
C++ : unique_ptr : 유니크 포인터 개념, 필요성, 장점, 활용법 스마트 포인터 - unique_ptr - shared_ptr - weak_ptr 예시: 포인터 #include "Vector.h" int main () { Vector* myVector = new Vector(10.f, 30.f); // delete myVector; return 0; } 항상 포인터를 생성하는 순간, delete를 구현해주어야 합니다. 하지만 프로그래머들이 가끔 실수를 할 수 있습니다. 더 이상 포인터가 필요하지 않을 때 메모리를 해제해야 합니다. 스마트 포인터를 쓰면 delete를 직접 호출할 필요가 없습니다. 그리고 가비지 컬렉션보다 빨라집니다. unique_ptr #include #include "Vector.h" int main() { std::unique_ptr myVector..
C++ : std::array : 개념, 장점, 단점, 필요성, 활용성, 예제, 구현 std::array 요소 수를 기억하지 않습니다. 단순히 C 스타일 배열을 추상화한 것이라 생각하면 좋습니다. 요소 수를 기억하지 못하므로 std::array가 아쉬울 수 있습니다. 아마 std::algorithm을 쓸 수 있고, 반복자를 쓸 수 있어서 나온 것일까요. 현재 사이즈를 접근할 필요가 없고, 고정형 크기의 배열이 필요하다면 선택지로 사용할 수 있는 컨테이너라는 생각이 들었습니다. 다만 프로젝트에서 그러한 경우가 그렇게 많지 않을 것으로 생각이 되었는데, 만약 그러한 상황이어도 굳이, 익숙하지 않은 array를 꺼내지 않아도 얼마든지 다른 방법으로도 충분히 해결 가능합니다. 이러한 컨테이너가 있다는 것을 기억해두고 좋은 기회가 오면 활용해보는 것도 좋을 것 같습니다. #include int m..