unique_ptr, shared_ptr 읽히기
Program Lang./C++ 2016. 12. 30. 14:451. 목적
c++ unique_ptr, shared_ptr 개인적인 정리
2. shared_ptr
C++98 표준안까지 사용되던 auto_ptr은 이제 더 이상 사용하지 않는 것이 권고 사항이다. C++11부터 지원하는 share_ptr을 간단히 말하면 객체의 자동 파괴를 수행하기 위해서 도입된 smart pointer 이다. 하지만 몇 가지 제약 사항은 여전히 존재한다. 제약 사항은 아래에서 하나씩 살펴보도록 하자.
일반적인 사용법은 테스트 코드에 주석으로 표기하였다. 자세한 사항은 standard 생성자 overriding을 참조하면 된다.
다만 주의해야 할 사항은 대입 연산은 explicit으로 처리되어 있기 때문에 암시적 대입연산은 동작하지 않는다.
또한 make_shared<> utility를 사용하는 것이 성능면에서 좋다.
2.1. shared_ptr 예제 (제약 사항 예제)
The C++ Standard Library 책의 예제는 너무 복잡하고 딱히 와 닿지도 않아서 어떤 블로그 소스 참조
하나의 객체에 대해서 서로 다른 shared_ptr로 참조하게 되면 소멸된 객체에 다시 소멸자를 호출하게 되어서 알 수 없는 동작을 수행하게 된다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | #include <iostream> #include <memory> #include <string> class Person { public : std::string name; //std::shared_ptr<Person> mfriend; std::weak_ptr<Person> mfriend; Person( const std::string& _name) : name(_name) { std::cout << __FUNCTION__ << ", " << __LINE__ << std::endl; } virtual ~Person() { std::cout << __FUNCTION__ << ", " << __LINE__ << std::endl; } }; int main() { // 임시객체 생성 Person *pPerson = new Person( "heesoon.kim" ); std::shared_ptr<Person> p1(pPerson , [](Person *p) { std::cout << "delete : " << p->name << std::endl; delete p; }); std::shared_ptr<Person> p2(pPerson, [](Person *p) { std::cout << "delete : " << p->name << std::endl; delete p; }); return 0; } |
<실행결과>
Start
Person, 14 delete : heesoon.kim ~Person, 18 delete : heesoon.kim
Segmentation fault
Finish
순환 참조의 문제점을 보여주는 예제로 weak_ptr<Person> 주석을 막고 shared_ptr<Person>을 사용하면 소멸자가 호출되지 않는다. 결론적으로 객체가 정상적으로 파괴되지 않는 문제가 발생한다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | #include <iostream> #include <memory> #include <vector> #include <string> class Person { public : std::string name; //std::shared_ptr<Person> mfriend; std::weak_ptr<Person> mfriend; Person( const std::string& _name) : name(_name) { std::cout << __FUNCTION__ << ", " << __LINE__ << std::endl; } virtual ~Person() { std::cout << __FUNCTION__ << ", " << __LINE__ << std::endl; } }; int main() { // 1. default shared_ptr usage //std::shared_ptr<Person> kim(new Person("kim")); //std::shared_ptr<Person> lee(new Person("lee")); // 2. user define delete function std::shared_ptr<Person> kim( new Person( "kim" ), [](Person *p) { std::cout << "delete : " << p->name << std::endl; delete p; }); std::shared_ptr<Person> lee( new Person( "lee" ), [](Person *p) { std::cout << "delete : " << p->name << std::endl; delete p; }); // 3. using utility make_shared usage //std::shared_ptr<Person> kim = std::make_shared<Person>("kim"); //std::shared_ptr<Person> lee = std::make_shared<Person>("lee"); std::cout << "( " << kim.use_count() << ", " << lee.use_count() << ")" << std::endl; kim->mfriend = lee; std::cout << "( " << kim.use_count() << ", " << lee.use_count() << ")" << std::endl; lee->mfriend = kim; std::cout << "( " << kim.use_count() << ", " << lee.use_count() << ")" << std::endl; return 0; } |
2.3. shared_ptr 예제 (제약 사항 예제)
smart pointer라고는 하지만 여전히 주의를 기울여야 할 것이 남아 있다. weak_ptr은 shared_ptr의 reference_count를 늘리지 않지만 shared_ptr이 관리하는 객체를 공유한다. 객체의 자원 관리는 shared_ptr로 하되 객체에 접근하여 필요한 동작을 수행 시에는 weak_ptr로 하는 것이 바람직해 보인다.
'Program Lang. > C++' 카테고리의 다른 글
[json-c] simple parsing example (0) | 2017.01.09 |
---|---|
std::function 정리 (0) | 2017.01.02 |
c++ pair 읽히기 (0) | 2016.12.30 |
full version (pat, pmt, sdt) (2) | 2016.07.22 |
sdt json version (0) | 2016.07.22 |