Boost::shared_ptr instantiated using this
Consider the following case:
typedef boost::shared_ptr<B> B开发者_开发知识库Ptr;
class A
{
public:
A() { b_ptr = BPtr(new B); }
void a_func() { C::c_func(b_ptr); }
private:
BPtr b_ptr;
}
class B
{
public:
B() { b_ptr = BPtr(this); }
void b_func() { C::c_func(b_ptr); }
private:
BPtr b_ptr;
}
class C
{
public:
static void c_func(BPtr b_ptr) { /*...*/ }
}
Is it ok to instantiate a shared_ptr with this
?
I'm guessing I'm doing something fundamentally wrong.
I also thought about using dependency injection of b_ptr to B's constructor, but that too seems very wrong.UPDATE:
To clarify - Both A and B need to use C::c_func. In turn, after some processing, C needs to call a callback function in B which I haven't specified above. Actually two cases are interesting:- If there's a requirement that C won't be stateful - then it needs to receive BPtr both from A and from B as in the code above.
- If C is stateful and both A and B instantiate separate C instances, giving a BPtr in C's ctor.
Is it ok to instantiate a shared_ptr with this?
No, for at least several reasons:
If you create a
A
orB
object on the stack or statically, you end up with ashared_ptr
"owning" the object created on the stack; when the object is destroyed, theshared_ptr
destructor will be called, callingdelete
on the object, and only Bad Things Will Happen. Further, even if the object is created dynamically, you don't know for sure what the owner of your class may do with it: he may assign it to some other type of smart pointer like anauto_ptr
, which has totally different semantics.You end up with a circular reference. For example,
b_ptr
owns theB
object of which it is a member. You have to manually.reset()
it in order for theB
object to be destroyed.
You can get a shared_ptr
from this
by using enable_shared_from_this
, but there are a lot of caveats: namely, you cannot call enable_shared_from_this
in a constructor. Even so, you don't want to store a shared_ptr
to an object inside of the object itself; it doesn't make any sense.
I'm guessing I'm doing something fundamentally wrong.
Yes, but since you haven't said what, exactly, you are trying to do, it's hard to say what you should be doing instead. You've only told us how you are trying to do this, not what you are trying to do in the first place.
I would recommend that you re-design to use std::enable_shared_from_this, e.g.
class B
{
B();
public:
std::shared_ptr<B> create() { return std::make_shared<B>(); } // Make sure B is allocated as shared_ptr inorder to ensure that shared_from_this() works.
};
However, if it's an API issue you have then you can do the following (although I don't recommend it).
void b_func() { C::c_func(BPtr(this, [](B*){})); } // Empty deleter. Nothing happens when shared_ptr goes out of scope. Note that c_func cannot take ownership of the pointer.
精彩评论