Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

weak_from_this() within constructor

I know you can't use shared_from_this from within a constructor. But is it ok to use the new weak_from_this from within a constructor? According to cppreference:

This is a copy of the the private mutable weak_ptr member that is part of enable_shared_from_this.

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this/weak_from_this

I don't see an issue in obtaining a copy of the internally stored weak_ptr from within the constructor, but I might be missing something, so I'm not sure on this.

like image 770
Björn M.P. Avatar asked May 28 '18 00:05

Björn M.P.


1 Answers

You can call it, but the weak_ptr will usually just be empty.

The point of shared_from_this is not to just make some shared_ptr, but to get a shared_ptr which shares ownership with the set of existing shared_ptr pointers. And the point of weak_ptr is to provide a way of getting a shared_ptr which shares ownership if other shared_ptr pointers exist at the time, without extending the lifetime like directly storing a shared_ptr would. So if no shared_ptr pointers to the object exist, a weak_ptr can't point at the same object.

Note that in normal use, when you do something like

std::shared_ptr<MyClass> p(new MyClass);

the sequence is:

  1. The implementation calls operator new(sizeof(MyClass)) to get some storage.

  2. The implementation calls a constructor of MyClass to create an object within that storage.

    • If MyClass inherits a specialization of std::enable_shared_from_this, it contains a std::weak_ptr subobject. The default constructor of weak_ptr is used to create an empty smart pointer.
  3. The implementation calls a constructor of std::shared_ptr<MyClass> to create a smart pointer, passing the pointer to the MyClass object.

    • The constructor of shared_ptr checks for whether the pointer points at a class type that inherits a compatible std::enable_shared_from_this specialization. If it does, the std::weak_ptr subobject within the class object is reassigned to be a copy of the shared_ptr being constructed.

So within the constructor of MyClass, you'd be within step 2. But the internal pointer used by shared_from_this() and weak_from_this() doesn't become useful until step 3.

[A similar reassignment of the weak_ptr happens during std::make_shared and std::allocate_shared. In those cases, the Standard doesn't obviously say that the weak_ptr is assigned after the complete pointed-at object is created, but it would be very unusual and unexpected for an implementation to go to extra effort to somehow magically do something to the weak_ptr at some point in between constructing the enable_shared_from_this base subobject and executing the derived class constructor body.]

It's possible you could create a std::shared_ptr which points at this from within a class constructor, to store it in some other variable or container or something. (But if using the default deleter, make sure you somehow know the object was actually created with scalar new!) After that point, both shared_from_this() and weak_from_this() can be used within the constructor and will return something connected to the already-created std::shared_ptr. But this seems rather inside-out from the normal way of doing things.

like image 87
aschepler Avatar answered Sep 28 '22 06:09

aschepler