Ce face std::enable_shared_from_this
Uneori o metodă trebuie să dea altcuiva un shared_ptr către obiectul curent (de exemplu se înregistrează într-o listă). std::shared_ptr<T>(this) ar crea un al doilea contor și obiectul ar fi șters de două ori.
Soluția: clasa moștenește std::enable_shared_from_this<T>, iar în metode apelezi shared_from_this(). Primești un shared_ptr care împarte contorul cu cei existenți.
Funcționează doar dacă obiectul este deja deținut de un shared_ptr (creat de obicei cu std::make_shared). Altfel, din C++17, se aruncă std::bad_weak_ptr.
Ce returnează
shared_from_this() returnează un std::shared_ptr<T> care împarte proprietatea cu ceilalți.
Exemple
Exemplul 1: Un abonat care se înregistrează singur
#include <memory>
#include <print>
#include <string>
#include <vector>
struct Abonat;
std::vector<std::shared_ptr<Abonat>> lista;
struct Abonat : std::enable_shared_from_this<Abonat> {
std::string nume;
explicit Abonat(std::string n) : nume(std::move(n)) {}
void inscrie() { lista.push_back(shared_from_this()); }
};
int main() {
auto ana = std::make_shared<Abonat>("Ana");
ana->inscrie();
std::println("În listă: {}", lista[0]->nume);
std::println("proprietari: {}", ana.use_count());
}
Rezultat
În listă: Ana
proprietari: 2
Exemplul 2: Obiect care nu este deținut de shared_ptr
Pe un obiect obișnuit (pe stivă), shared_from_this() aruncă std::bad_weak_ptr.
#include <memory>
#include <print>
struct Nod : std::enable_shared_from_this<Nod> {};
int main() {
Nod n;
try {
auto p = n.shared_from_this();
} catch (const std::bad_weak_ptr& e) {
std::println("Eroare: {}", e.what());
}
}
Rezultat
Eroare: bad_weak_ptr
Greșeli frecvente
- Moștenești
enable_shared_from_thisprivat (de exemplu cuclassfărăpublic). Mecanismul nu mai funcționează; moștenirea trebuie să fie publică. - Apelezi
shared_from_this()în constructor. În acel moment obiectul nu este încă deținut de niciunshared_ptr.
Comenzi înrudite
std::shared_ptr: Pointer inteligent cu proprietate comună: obiectul este șters când ultimul shared_ptr dispare.std::weak_ptr: Referință slabă la un obiect deținut de shared_ptr: nu îl ține în viață; lock() îl folosește în siguranță.this: Pointer către obiectul curent, disponibil în orice metodă nestatică a unei clase.