std::enable...d_from_this(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

πŸ’… NAME

std::enable_shared_from_this::shared_from_this β€” yes bestie, that's std::enable_shared_from_this::shared_from_this, the one and only πŸ’–

Ok so real quick, this page lives in the C++ Standard Library section of the manual β€” it's std::enable...d_from_this(3), the truncated-looking one. Don't let the name scare you, it's giving "long title, simple job" energy.


✨ Synopsis ✨

std::shared_ptr<T> shared_from_this();             (1) (since C++11)
std::shared_ptr<T const> shared_from_this() const; (2) (since C++11)

So what does it do? It returns a std::shared_ptr<T> that shares ownership of *this with all the existing std::shared_ptrs that refer to *this. Like, it's the "hey, I'm already owned, let me hand you a proper share of me" move 🫢

Effectively it executes std::shared_ptr<T>(weak_this), where weak_this is the exposition-only mutable std::weak_ptr<T> member of enable_shared_from_this. Yes, exposition-only, no cap β€” it's a real member that the standard just describes rather than names for you πŸ’€


πŸŽ€ Return value

A std::shared_ptr<T> that shares ownership of *this with pre-existing std::shared_ptrs. That's it, that's the tea πŸ‘‘


😭 Exceptions

Listen closely bestie, this is the important one:

If shared_from_this is called on an object that is not previously shared by std::shared_ptr, std::bad_weak_ptr is thrown β€” and it's thrown by the shared_ptr constructor from a default-constructed weak_this. So like, don't call this on a stack object and expect it to slay. It will not. It will throw 🚨

🌸 Example

// Run this code

#include <iostream>
#include <memory>

struct Foo : public std::enable_shared_from_this<Foo>
{
    Foo() { std::cout << "Foo::Foo\n"; }
    ~Foo() { std::cout << "Foo::~Foo\n"; }
    std::shared_ptr<Foo> getFoo() { return shared_from_this(); }
};

int main()
{
    Foo *f = new Foo;
    std::shared_ptr<Foo> pf1;

    {
        std::shared_ptr<Foo> pf2(f);
        pf1 = pf2->getFoo(); // shares ownership of object with pf2
    }

    std::cout << "pf2 is gone\n";
}

✨ Output:

Foo::Foo
pf2 is gone
Foo::~Foo

Look at that destructor firing after pf2 is gone β€” because pf1 is still holding on, bestie. Shared ownership, iconic behaviour πŸ”₯


πŸ¦‹ Defect reports

The following behavior-changing defect reports were applied retroactively to previously published C++ standards. (Retroactive glow-ups, we love to see it πŸ’…)

  • LWG 2529 β€” applied to C++11.
    • Behavior as published: calling shared_from_this on an unshared object was undefined behavior.
    • Correct behavior: std::bad_weak_ptr is thrown. Much better. Way less "hope for the best" energy πŸ™ˆ

🌈 See also

  • shared_ptr β€” smart pointer with shared object ownership semantics (C++11) (class template)

Ok that's the whole page, go forth and share your ownership responsibly πŸ§šπŸ’œ

Sign-off szn: this lil masterpiece came from http://cppreference.com, dated 2024.06.10, and it's filed under std::enable...d_from_this(3). K bye, ily, stan smart pointers πŸŽ€βœ¨

πŸ“¦ where this page comes from