Soru Bunun için bir destek :: shared_ptr alma


Yaygın olarak kullanıyorum boost:shared_ptr benim kodumda Aslında, yığın üzerinde tahsis edilen nesnelerin çoğu bir shared_ptr. Ne yazık ki bu geçemediğim anlamına geliyor this herhangi bir işlev içine alır shared_ptr. Bu kodu düşünün:

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

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

Burada iki problem mevcut. İlk olarak, bu derleme yapmaz çünkü T * yapıcısı shared_ptr açık. İkincisi, onu inşa etmek için zorlarsam bar(boost::shared_ptr<Foo>(this)) Nesneme ikinci bir paylaşımlı işaretçi yaratacağım ve sonuçta bir çift silme işlemine yol açacak.

Bu bana şu soruyu getiriyor: Bu nesnelerden birindeki bir yöntem içinde var olan mevcut paylaşımlı işaretçinin bir kopyasını almak için standart bir model var mı? Burada tek seçeneğimi saymak intrusive referans kullanıyor mu?


76
2017-09-26 22:42


Menşei


"Burada tek seçeneğimi saymak intrusive referans kullanıyor mu?"Bu seçenekte sorun nedir? - curiousguy
Belki hiçbir şey. Durumunuza göre değişir. Nesnelerinizi büyütür ve smartpointer'leri tuttuğunuz sınıflar üzerinde kontrole sahip olmadığınız yerlerde çalışmayabilir. - Joe Ludwig
enabe_shared_from_this şu anda std:: . Cevabıma bir bak. - Johan Lundberg


Cevaplar:


Türetmek enable_shared_from_this ve sonra kendi kendinize ait bir nesneye ortak bir işaretçi oluşturmak için "bu" yerine "shared_from_this ()" öğesini kullanabilirsiniz.

Bağlantıdaki örnek:

#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
}

Bir üye işlevinden iş parçacığı oluşturmak için konuların yumuşatılması, bunun yerine bir shared_from_this () öğesine bağlandığında iyi bir fikirdir. Nesnenin serbest bırakılmamasını sağlayacaktır.


102
2017-09-26 22:46



f () ".Copy ()" gibidir ve aynı zamanda sığ bir kopyadır. - Anton Andreev


Sadece shared_ptr yerine işlev parametreniz için bir ham işaretçiyi kullanın. Akıllı bir işaretçinin amacı, nesnenin kullanım ömrünü kontrol etmektir, ancak nesnenin kullanım ömrü C ++ kapsam kuralları ile garanti edilmiştir: en azından işlevinizin sonuna kadar var olacaktır. Yani, çağıran kod, işlev döndürmeden önce nesneyi silemez; Böylece, "aptal" işaretçisinin güvenliği, işlevinizin içindeki nesneyi silmeye çalışmadığınız sürece garanti edilir.

Bir function_ptr işlevini bir işleve iletmeniz gereken tek zaman, nesnenin sahipliğini işleve aktarmak istediğinizde veya işlevin işaretçinin bir kopyasını almasını istemektir.


19
2017-09-27 03:59



Kabul. Birçok kez foo (const Object * object_ptr) {} foo (obj.get ()); obj bir destektir :: shared_ptr <Object>. Herb Sutter için web üzerinde arama yapın, bu ve benzeri konularda bazı büyük bilgi sahibi olan bir başka ve makale yazarıdır. - bn.
Bu noktanın biraz yanında, ancak ... Eğer işaretçiyi kullanabiliyorsanız, o zaman (büyük olasılıkla) referansı kullanabilirsiniz, bu da daha iyi IMO'dur. - denis-bu
@ denis-bu, ne zaman bir NULL işaretçi bir olasılıktır. Ama iyi bir nokta çiziyorsun. - Mark Ransom


destek bu kullanım için bir çözüm var, onay enable_shared_from_this


14
2017-09-26 22:44





Gerçekten bar içindeki pFoo'nun daha fazla paylaşılan kopyasını mı yapıyorsunuz? İçinde çılgın bir şey yapmıyorsan, şunu yap:


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

9
2017-09-26 23:07





C ++ 11 ile shared_ptr ve enable_shared_from_this şimdi standart kütüphanede. İkincisi, isminden de anlaşılacağı gibi, bu dava için tam olarak.

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

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

Yukarıdaki bağlantılarda bunun üzerine örnek teşkil etmektedir:

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

kullanın:

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





İşaretçiyi kabul eden işlev, iki davranıştan birini yapmak ister:

  • Nesnenin sahibi geçirilmekte ve kapsam dışı olduğunda silinmektedir. Bu durumda, X * 'i kabul edip hemen o nesnenin etrafına bir scoped_ptr sarın (işlev gövdesinde). Bu, "bu" ya da genel olarak, herhangi bir yığın-ayrılmış nesne kabul etmek için çalışacaktır.
  • İşaretçiyi paylaş Geçirilen nesneye (sahip olmayın). Bu durumda değil İşlevin sonunda nesneyi silmek istemediğinizden, bir scoped_ptr kullanmak istiyorum. Bu durumda, teorik olarak istediğiniz şey bir shared_ptr'dir (ona başka bir yerde linked_ptr denir). Destek kütüphanesi vardır shared_ptr bir sürümüve bu da Scott Meyers'ın C ++ kitabında (3. baskıda madde 18) tavsiye edilir.

Düzenle: Maalesef soruyu biraz yanlış anladım ve şimdi bu cevabın sorunun tam olarak ele alındığını görüyorum. Benzer kod üzerinde çalışan herkes için yararlı olabileceğinden, yine de bırakacağım.


3
2017-09-27 00:26