2014-06-26 11 views
14

Pracuję z wykorzystaniem bazy kodowej, która została częściowo zaimplementowana przez kogoś, kto był zakochany w zbyt złożonych rozwiązaniach prostych problemów (np. Klas szablonów z dwoma parametrami, które były tworzone tylko dla jednej pary typów). Jedną z rzeczy, które robiła, było tworzenie obiektów w inteligentnym wskaźniku, a następnie przechowywanie obiektu w słabym wskaźniku.Przechowuj słabe wskaźniki do siebie

class MyClass { 
    //... 
    boost::weak_ptr<MyClass> m_self; 
    //... 
}; 

boost::shared_ptr<MyClass> 
Factory::Factory::Factory::CreateMyClass() { 
    boost::shared_ptr<MyClass> obj(new MyClass(...)); 
    boost::weak_ptr<MyClass> p(obj); 
    obj->storeSelfPointer(p); 
    return obj; 
} 

Ta klasa kontynuuje używanie m_self, blokując ją i przekazując wynikowy współdzielony wskaźnik.

Za życie mnie nie mogę pojąć, co ona próbowała osiągnąć. Czy istnieje jakiś wzorzec lub idea, które wyjaśniałyby tę implementację? Wydaje mi się, że to zupełnie bezcelowe i chciałbym to odrzucić.

EDYTOWANIE: Powinienem wspomnieć, że żadne z miejsc, które używają wynikowego inteligentnego wskaźnika uzyskanego z blokowania m_self w rzeczywistości nie zachowuje inteligentnego wskaźnika.

+5

nie wiedział o 'std :: shared_from_this' Chyba –

+0

Jest C++ 98, nowsze rzeczy nie jest używany –

+3

No ok, to C++ 98 wersja' enable_shared_from_this' –

Odpowiedz

17

Możliwym zastosowaniem tego "projektu" może być użycie m_self.lock() do generowania współdzielonych wskaźników z tego.

Jeśli usuniesz ten słaby element wskaźnika, licznik odwołań wstrzymany przez wygenerowany współdzielony wskaźnik z this będzie niepoprawny.

Osiąga to samo niż std::enable_shared_from_this, co ciekawe, cppreference.com mentions this design:

Wspólna realizacja dla enable_shared_from_this jest utrzymywanie słabego odniesienia (takie jak std :: weak_ptr) do tego. Konstruktorzy std :: shared_ptr wykryć obecność enable_shared_from_this bazy i przypisać nowo utworzonego std :: shared_ptr do przechowywane wewnętrznie słabego odniesienia

a standard C++, sekcja 20.8.2.4 § 10, wspominając ten sam możliwej realizacji:

konstruktorów shared_ptr, które tworzą unikalne wskaźniki mogą wykryć obecność enable_shared_- bazy from_this i przypisać nowo utworzonego shared_ptr jego __weak_this membe r


Możliwa Refaktoryzacja:

  • Jeśli używasz C++ 11, można usunąć element std::weak_ptr i publicznie dziedziczy std::enable_shared_from_this<T>. Powinieneś pobrać współdzielony wskaźnik, dzwoniąc pod numer shared_from_this().

  • Jeśli nie używasz C++ 11, ale możesz użyć doładowania, użyj boost::enable_shared_from_this, zobacz boost documentation. Powinieneś pobrać współdzielony wskaźnik, dzwoniąc pod numer shared_from_this().

  • Jeśli nie używasz C++ 11, i nie może korzystać impuls, można wnieść proponowanego wdrożenia standardu do bazy kodu, jest na tyle krótki:

Code : (skopiowane z § 20.8.2.4 - 11, usunąć wiodącym podkreślenia, i prawdopodobnie chcesz zmienić jego nazwę)

template<class T> class enable_shared_from_this { 
    private: 
    weak_ptr<T> __weak_this; 
    protected: 
    constexpr enable_shared_from_this() : __weak_this() { } 
    enable_shared_from_this(enable_shared_from_this const &) { } 
    enable_shared_from_this& operator=(enable_shared_from_this const &) { return *this; } 
    ~enable_shared_from_this() { } 
    public: 
    shared_ptr<T> shared_from_this() { return shared_ptr<T>(__weak_this); } 
    shared_ptr<T const> shared_from_this() const { return shared_ptr<T const>(__weak_this); } 
}; 

i używać shared_from_this() aby wspólny wskaźnik. Jeśli skopiujesz ten kod, zwróć uwagę, że konstruowanie współdzielonych wskaźników za pomocą innych metod nie działałoby nie działa. Współdzielone konstruktory wskaźników muszą zostać zmodyfikowane (co wyjaśnia standardowy cytat powyżej).

+1

To nie jest oficjalna dokumentacja. –

+1

Prawda. W rzeczywistości standard pokazuje dokładnie tę samą możliwą implementację. – quantdev

+0

Tak, próbowałem to potwierdzić, ale wyszukiwanie w pliku PDF nie działało. Teraz to widzę. –