Why shared_from_this can't be used in constructor from technical standpoint?
Asked Answered
F

2

54

In the book The C++ Standard Library at page 91 I have read this about shared_from_this():

The problem is that shared_ptr stores itself in a private member of Person’s base class, enable_shared_from_this<>, at the end of the construction of the Person.

The relevant code snippet from the book is:

class Person : public std::enable_shared_from_this<Person> {
   ...
};

I don't understand two things here:

  1. who is this shared_ptr which stores itself?
  2. how he can store itself anywhere at the end of the construction of Person? I think construction of Person ends up with the last statement of its constructor which written by me.

I understand that there is weak_ptr which hasn't been initialized yet.

EDIT: Thanks to Angew! shared_from_this will work only after first shared_ptr to Person was created. This shared_ptr will check if Person class inherited from enable_shared_from_this, and if yes then initialize its internal weak_ptr.

Feola answered 10/8, 2015 at 16:14 Comment(2)
I hadn't realized that you were probably just asking for these NotesSkink
@MarcoA. Great, these notes really helpful!Feola
D
75

The reason is simple: in object X, enable_shared_from_this works by initialising a hidden weak_ptr with a copy of the first shared_ptr which points to object X. However, for a shared_ptr to be able to point to X, X must already exist (it must be already constructed). Therefore, while the constructor of X is running, there is yet no shared_ptr which enable_shared_from_this could use.

Take this piece of code:

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

Before the constructor of p (of the shared_ptr) is even called, its argument must be evaluated. That argument is the expression new Person(). Therefore, the constructor of Person runs before the constructor of p has even begun—before there is any shared_ptr object to which enable_shared_from_this could bind.

Dogcart answered 10/8, 2015 at 16:24 Comment(3)
"...enable_shared_from_this works by initialising a hidden weak_ptr with a copy of the first shared_ptr which points to object X. " What procedure is responsible for initializing this hidden weak_ptr? How does it know what the "first" shared_ptr that points to X is?Jobless
@Chad See the notes here for some information: en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptrHumanist
Thanks @Holt. Looks like a constructor of shared_ptr is responsible for initializing the weak_ptr. Only those constructors that take a raw pointer (e.g. a pointer returned from a call to new) do the initialization. Copy constructors don't. Since only only the first shared_ptr to X should be constructed from a raw pointer (others are usually copy-constructed), the weak_ptr is initialized by the first shared_ptr to X.Jobless
T
0

Therefore, while the constructor of X is running, there is yet no shared_ptr which enable_shared_from_this could use.

But for the case when make_shared is called it can be possible to access a control block to create a weak_ptr before/while constructor of class working, because they are created in the same allocated memory block with the class.

Tropophilous answered 12/11, 2023 at 22:3 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.