Pytanie Pobranie :: shared_ptr dla tego


Korzystam z szerokiego zastosowania boost:shared_ptr w moim kodzie. W rzeczywistości większość obiektów przydzielonych do sterty jest przechowywanych przez shared_ptr. Niestety oznacza to, że nie mogę przejść this do dowolnej funkcji, która wymaga shared_ptr. Rozważ ten kod:

void bar(boost::shared_ptr<Foo> pFoo)
{
    ...
}

void Foo::someFunction()
{
    bar(this);
}

Są tu dwa problemy. Po pierwsze, nie skompiluje się, ponieważ konstruktor T * dla shared_ptr jest wyraźny. Po drugie, jeśli zmuszę go do budowania bar(boost::shared_ptr<Foo>(this)) Stworzę drugi wspólny wskaźnik do mojego obiektu, który ostatecznie doprowadzi do podwójnego usunięcia.

Prowadzi mnie to do mojego pytania: czy istnieje jakiś standardowy wzorzec do uzyskania kopii istniejącego współdzielonego wskaźnika, o którym wiesz, że istnieje wewnątrz metody na jednym z tych obiektów? Czy używam intruzywnego odnośnika, licząc tutaj moją jedyną opcję?


76
2017-09-26 22:42


pochodzenie


"Czy używam intruzywnego odnośnika, licząc tutaj moją jedyną opcję?"Co jest nie tak z tą opcją? - curiousguy
Może nic. Zależy od twoich okoliczności. Powoduje, że twoje obiekty są większe i mogą nie działać w miejscach, w których nie masz kontroli nad klasami, na których trzymasz smartfony. - Joe Ludwig
enabe_shared_from_this jest teraz w std:: . Spójrz na moją odpowiedź. - Johan Lundberg


Odpowiedzi:


Możesz czerpać z enable_shared_from_this a następnie możesz użyć "shared_from_this ()" zamiast "this", aby spawnować wspólny wskaźnik do twojego własnego obiektu self.

Przykład w linku:

#include <boost/enable_shared_from_this.hpp>

class Y: public boost::enable_shared_from_this<Y>
{
public:

    shared_ptr<Y> f()
    {
        return shared_from_this();
    }
}

int main()
{
    shared_ptr<Y> p(new Y);
    shared_ptr<Y> q = p->f();
    assert(p == q);
    assert(!(p < q || q < p)); // p and q must share ownership
}

To dobry pomysł, gdy spawnie wątki z funkcji składowej, aby zwiększyć: bind do shared_from_this () zamiast tego. Zapewni to, że obiekt nie zostanie zwolniony.


102
2017-09-26 22:46



f () jest jak ".Copy ()" i jest płytką kopią. - Anton Andreev


Po prostu użyj surowego wskaźnika dla swojego parametru funkcji zamiast shared_ptr. Celem inteligentnego wskaźnika jest kontrolowanie czasu życia obiektu, ale czas życia obiektu jest już zagwarantowany przez reguły ustalania zasięgu C ++: będzie istnieć co najmniej tak długo, jak koniec funkcji. Oznacza to, że kod wywołujący nie może usunąć obiektu przed powrotem funkcji; w ten sposób zagwarantowane jest bezpieczeństwo "głupiego" wskaźnika, o ile nie spróbujesz usunąć obiektu wewnątrz swojej funkcji.

Jedynym momentem, w którym musisz przekazać shared_ptr do funkcji, jest przekazanie prawa własności obiektu do funkcji lub funkcja wykonania kopii wskaźnika.


19
2017-09-27 03:59



Zgoda. Wiele razy możesz użyć foo (const Object * object_ptr) {} foo (obj.get ()); gdzie obj to boost :: shared_ptr <Obiekt>. Czy wyszukiwania w Internecie dla Herb Sutter, jest inny i autor artykułów, który ma kilka świetnych informacji na temat tego i podobnych problemów. - bn.
Nie ma to znaczenia, ale ... Jeśli możesz użyć wskaźnika, to (najprawdopodobniej) możesz użyć odniesienia, które jest lepszym IMO. - denis-bu
@ denis-bu, z wyjątkiem sytuacji, gdy a NULL wskaźnik to możliwość. Ale robisz dobry punkt. - Mark Ransom


boost ma rozwiązanie dla tego przypadku użycia, sprawdź enable_shared_from_this


14
2017-09-26 22:44





Czy naprawdę tworzysz więcej wspólnych kopii pFoo na pasku? Jeśli nie robisz w środku niczego szalonego, po prostu zrób to:


void bar(Foo &foo)
{
    // ...
}

9
2017-09-26 23:07





Z C ++ 11 shared_ptr i enable_shared_from_this jest teraz w standardowej bibliotece. Ta ostatnia jest, jak sama nazwa wskazuje, dokładnie w tym przypadku.

http://en.cppreference.com/w/cpp/memory/shared_ptr

http://pl.cppreference.com/w/cpp/memory/enable_shared_from_this

Przykład opiera się na tym w powyższych linkach:

struct Good: std::enable_shared_from_this<Good>{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};

posługiwać się:

std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';

5
2017-12-25 13:08





Funkcja akceptująca wskaźnik chce wykonać jedno z dwóch zachowań:

  • Włóż obiekt przekazane i usunąć, gdy wykracza poza zakres. W takim przypadku możesz po prostu zaakceptować X * i natychmiast owinąć obiekt scoped_ptr wokół tego obiektu (w treści funkcji). Będzie to działać, aby zaakceptować "ten" lub, ogólnie rzecz biorąc, dowolny obiekt alokowany przez stertę.
  • Udostępnij wskaźnik (nie należy do niego) do obiektu, który jest przekazywany. W tym przypadku robisz nie chcesz w ogóle użyć scoped_ptr, ponieważ nie chcesz usuwać obiektu na końcu swojej funkcji. W tym przypadku teoretycznie potrzebujesz pliku shared_ptr (widziałem go w innym miejscu, link_ptr). Biblioteka boostów ma wersja shared_ptri jest to również zalecane w książce Scott Meyers Effective C ++ (pozycja 18 w trzeciej edycji).

Edytować: Ups, nieznacznie błędnie przeczytałem pytanie, a teraz widzę, że ta odpowiedź nie jest dokładnie odpowiedzią na to pytanie. Zostawię to mimo wszystko, na wypadek, gdyby to mogło być pomocne dla każdego, kto pracuje nad podobnym kodem.


3
2017-09-27 00:26