When should we use std::enable_shared_from_this

后端 未结 3 1556
逝去的感伤
逝去的感伤 2020-12-29 08:54

I just knew std::enable_shared_from_this form this link.
But after reading the code below, I don\'t know when to use it.

try {
        G         


        
相关标签:
3条回答
  • 2020-12-29 09:17

    There're some use case which you can't use the template std::shared_ptr<T> like opaque pointer.

    In that case, it's useful to have this:

    In some_file.cpp

    struct A : std::enable_shared_from_this<A> {};
    
    extern "C" void f_c(A*);
    extern "C" void f_cpp(A* a) {
       std::shared_ptr<A> shared_a = a->shared_from_this();
       // work with operation requires shared_ptr
    }
    
    int main()
    {
        std::shared_ptr<A> a = std::make_shared<A>();
        f_c(a.get());
    }
    

    In some_other.c

    struct A;
    void f_cpp(struct A* a);
    void f_c(struct A* a) {
        f_cpp(a);
    }
    
    0 讨论(0)
  • 2020-12-29 09:19

    Let's say I want to represent a computation tree. We'll have an addition represented as a class deriving from expression with two pointers to expressions, so an expression can be evaluated recursively. However, we need to end the evaluation somewhere, so let's have numbers evaluate to themselves.

    class Number;
    
    class Expression : public std::enable_shared_from_this<Expression>
    {
    public:
        virtual std::shared_ptr<Number> evaluate() = 0;
        virtual ~Expression() {}
    };
    
    class Number : public Expression
    {
        int x;
    public:
        int value() const { return x; }
        std::shared_ptr<Number> evaluate() override
        {
            return std::static_pointer_cast<Number>(shared_from_this());
        }
        Number(int x) : x(x) {}
    };
    
    class Addition : public Expression
    {
        std::shared_ptr<Expression> left;
        std::shared_ptr<Expression> right;
    public:
        std::shared_ptr<Number> evaluate() override
        {
            int l = left->evaluate()->value();
            int r = right->evaluate()->value();
            return std::make_shared<Number>(l + r);
        }
        Addition(std::shared_ptr<Expression> left, std::shared_ptr<Expression> right) :
            left(left),
            right(right)
        {
    
        }
    };
    

    Live on Coliru

    Note that the "obvious" way of implementing Number::evaluate() with return std::shared_ptr<Number>(this); is broken because it will result in double delete.

    0 讨论(0)
  • 2020-12-29 09:23

    The hint about when std::enable_shared_from_this<T> is useful is in its name: when yielding objects based on some requests it may be necessary to return a pointer to an object itself. If the result should be a std::shared_ptr<T> it becomes necessary to return such a pointer from within a member function where there is generally no std::shared_ptr<T> accessible.

    Having derived from std::enable_shared_from_this<T> provides a way to get hold of a std::shared_ptr<T> given just a pointer of type T. Doing so does, however, assume that the object is already managed via a std::shared_ptr<T> and it would create mayhem if the object is allocated on the stack:

    struct S: std::enable_shared_from_this<S> {
        std::shared_ptr<S> get_object() {
            return this->shared_from_this();
        };
    }
    
    int main() {
        std::shared_ptr<S> ptr1 = std::make_shared<S>();
        std::shared_ptr<S> ptr2 = ptr1->get_object();
        // ...
    }
    

    In a realistic scenario there is probably some condition under which a std::shared_ptr<T> to the current object is returned.

    0 讨论(0)
提交回复
热议问题