상세 컨텐츠

본문 제목

enable_shared_from_this

똑똑한 개발/C++

by 성댕쓰 2022. 4. 22. 12:45

본문

shared_ptr로 관리하고 있는 object ownership을 공유하는 또다른 shared_ptr pt1, pt2, ...을 만들 수 있는 기능을 제공한다.

publicly enable_shared_from_this를 상속하면 shared_from_this 함수를 사용할 수 있다.

T::shared_from_this 는 shared_ptr로 관리하고 있는 t와 ownership을 공유하는 new shared_ptr를 리턴한다.

Notes

보통 this에 weak_ptr을 멤버변수를 추가하여 enable_shared_from_this 구현한다.

Example

#include <memory>
#include <iostream>

struct Good : std::enable_shared_from_this<Good> // note: public inheritance
{
    std::shared_ptr<Good> getPtr()
    {
        return shared_from_this();
    }
};

struct Best : std::enable_shared_from_this<Best>
{
    std::shared_ptr<Best> getPtr()
    {
        return shared_from_this();
    }
    // No public constructor, only factory function,
    // so there's no way to have getPtr return nullptr.
    [[nodiscard]] static std::shared_ptr<Best> create()
    {
        // not using std::make_shared<Best> because the c'tor is private.
        return std::shared_ptr<Best>(new Best());
    }
private:
    Best() = default
};

struct Bad
{
    std::shared_ptr<Bad> getptr() {
        return std::shared_ptr<Bad>(this);
    }
    ~Bad() { std::cout << "Bad::~Bad() called\n"; }
};
 
void testGood()
{
    // Good: the two shared_ptr's share the same object
    std::shared_ptr<Good> good0 = std::make_shared<Good>();
    std::shared_ptr<Good> good1 = good0->getptr();
    std::cout << "good1.use_count() = " << good1.use_count() << '\n';
}
 
 
void misuseGood()
{
    // Bad: shared_from_this is called without having std::shared_ptr owning the caller 
    try {
        Good not_so_good;
        std::shared_ptr<Good> gp1 = not_so_good.getptr();
    } catch(std::bad_weak_ptr& e) {
        // undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17)
        std::cout << e.what() << '\n';    
    }
}
 
 
void testBest()
{
    // Best: Same but can't stack-allocate it:
    std::shared_ptr<Best> best0 = Best::create();
    std::shared_ptr<Best> best1 = best0->getptr();
    std::cout << "best1.use_count() = " << best1.use_count() << '\n';
 
    // Best stackBest; // <- Will not compile because Best::Best() is private.
}
 
 
void testBad()
{
    // Bad, each shared_ptr thinks it's the only owner of the object
    std::shared_ptr<Bad> bad0 = std::make_shared<Bad>();
    std::shared_ptr<Bad> bad1 = bad0->getptr();
    std::cout << "bad1.use_count() = " << bad1.use_count() << '\n';
} // UB: double-delete of Bad
 
 
int main()
{
    testGood();
    misuseGood();
 
    testBest();
 
    testBad();
}

output

good1.use_count() = 2
bad_weak_ptr
best1.use_count() = 2
bad1.use_count() = 1
Bad::~Bad() called
Bad::~Bad() called
*** glibc detected *** ./test: double free or corruption

 

참조 : std::enable_shared_from_this - cppreference.com

'똑똑한 개발 > C++' 카테고리의 다른 글

[boost] asio #1  (0) 2022.05.01
[Visual Studio] Character Set Unicode vs MBCS  (0) 2022.04.26
lvalue, rvalue 알아보자  (0) 2021.05.29
condition_variable에 대해서  (0) 2021.05.29
더블포인터에 대해서  (0) 2021.05.29

관련글 더보기

댓글 영역