Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shared_from_this called from constructor

Tags:

c++

boost

I have to register an object in a container upon its creation. Without smart pointers I'd use something like this:

a_class::a_class() {     register_somewhere(this); } 

With smart pointers I should use shared_from_this but I can't use that in the constructor.

Is there a clean way to solve this problem? What would you do in a similar situation? I'm thinking about introducing an init method to call just after creation and put everything in a factory function like this:

boost::shared_ptr<a_class> create_a() {     boost::shared_ptr<a_class> ptr(new a_class);     ptr->init();     return ptr; } 

Is it fine or there is a standard procedure to follow in such cases?

EDIT: Actually my case is more complex. I have 2 object which shall maintain pointers each other. So the truth is I'm not "registering" but creating another object (let's say b_class) which requires this as a parameter. b_class receives this as a weak pointer and stores it.

I'm adding this because since you are giving me design advices (which are very appreciated) at least you can know what I'm doing:

a_class::a_class() {     b = new b_class(this); } 

In my program a_class is an entity and b_class is one of the concrete classes representing the state (in the constructor it's just the starting state). a_class needs a pointer to the current state and b_class needs to manipulate the entity.

a_class is responsible for creating and destroying b_class instances and thus maintains a shared_ptr to them but b_class need to manipulate a_class and thus maintains a weak pointer. a_class instance "survives" b_class instances.

Do you suggest to avoid using smart pointers in this case?

like image 449
Emiliano Avatar asked Aug 03 '10 21:08

Emiliano


People also ask

Can you call Shared_from_this () in the constructor?

By deriving your class from the class template enable_shared_from_this , you inherit a method shared_from_this that returns a shared_ptr instance to this . Note(2) you cannot call enable_shared_from_this inside the constructor.

What is Shared_from_this?

shared_from_this. returns a shared_ptr which shares ownership of *this. (public member function)


2 Answers

a_class is responsible for creating and destroying b_class instances

...

a_class instance "survives" b_class instances.

Given these two facts, there should be no danger that a b_class instance can attempt to access an a_class instance after the a_class instance has been destroyed as the a_class instance is responsible for destroying the b_class instances.

b_class can just hold a pointer to it's associated a_class instance. A raw pointer doesn't express any ownership which is appropriate for this case.

In this example it doesn't matter how the a_class is created, dynamically, part of a aggregated object, etc. Whatever creates a_class manages its lifetime just as a_class manages the lifetime of the b_class which it instantiates.

E.g.

class a_class;  class b_class { public:     b_class( a_class* a_ ) : a( a_ ) {} private:     a_class* a; };  class a_class { public:     a_class() : b( new b_class(this) ) {} private:     boost::shared_ptr<b_class> b; }; 

Note, in this toy example there is no need for a shared_ptr, an object member would work just as well (assuming that you don't copy your entity class).

class a_class { public:     a_class() : b( this ) {} private:     b_class b; }; 
like image 155
CB Bailey Avatar answered Sep 20 '22 08:09

CB Bailey


If you absolutely need a shared_ptr during construction, it's best to have an 'init' function. In fact, this is the only decent approach I can think of. You should probably have a special function that creates objects of this type, to ensure init() is called, if you choose this path.

However, depending on what you're registering for, it may be a better idea to give whatever object you're registering with a plain pointer to the object in the constructor, rather than a shared_ptr. Then in the destructor, you can just unregister the object from the manager.

like image 37
Collin Dauphinee Avatar answered Sep 18 '22 08:09

Collin Dauphinee