Pertanyaan Mendapatkan dorongan :: shared_ptr untuk ini


Saya menggunakan ekstensif boost:shared_ptr dalam kode saya. Bahkan, sebagian besar objek yang dialokasikan di heap dipegang oleh a shared_ptr. Sayangnya ini berarti saya tidak bisa lulus this ke fungsi apa pun yang membutuhkan shared_ptr. Pertimbangkan kode ini:

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

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

ada dua masalah disini. Pertama, ini tidak dapat dikompilasi karena konstruktor T * untuk shared_ptr eksplisit. Kedua, jika saya memaksakannya untuk membangun bar(boost::shared_ptr<Foo>(this)) Saya akan membuat pointer bersama kedua ke objek saya yang akhirnya akan mengarah pada penghapusan-ganda.

Ini membawa saya ke pertanyaan saya: Apakah ada pola standar untuk mendapatkan salinan pointer bersama yang ada yang Anda tahu ada dari dalam metode pada salah satu objek tersebut? Apakah menggunakan referensi intrusif menghitung satu-satunya pilihan saya di sini?


76
2017-09-26 22:42


asal


Jawaban:


Anda dapat memperolehnya enable_shared_from_this dan kemudian Anda dapat menggunakan "shared_from_this ()" alih-alih "this" untuk menelurkan pointer yang dibagikan ke objek diri Anda sendiri.

Contoh di tautan:

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

Ini adalah ide yang bagus ketika memijah ulir dari fungsi anggota untuk meningkatkan :: mengikat ke shared_from_this () bukan ini. Ini akan memastikan bahwa objek tidak dilepaskan.


102
2017-09-26 22:46



Cukup gunakan pointer mentah untuk parameter fungsi Anda sebagai ganti dari shared_ptr. Tujuan dari pointer pintar adalah untuk mengontrol umur objek, tetapi umur objek sudah dijamin oleh aturan C ++ scoping: itu akan ada setidaknya selama akhir dari fungsi Anda. Artinya, kode panggilan tidak dapat menghapus objek sebelum fungsi Anda kembali; sehingga keamanan penunjuk "bodoh" dijamin, selama Anda tidak mencoba untuk menghapus objek di dalam fungsi Anda.

Satu-satunya waktu Anda harus melewatkan shared_ptr ke fungsi adalah ketika Anda ingin meneruskan kepemilikan objek ke fungsi, atau ingin fungsi untuk membuat salinan penunjuk.


19
2017-09-27 03:59



dorongan memiliki solusi untuk kasus penggunaan ini, periksa enable_shared_from_this


14
2017-09-26 22:44



Apakah Anda benar-benar membuat lebih banyak salinan bersama pFoo di dalam bar? Jika Anda tidak melakukan sesuatu yang gila di dalam, lakukan saja ini:


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

9
2017-09-26 23:07



Dengan C ++ 11 shared_ptr dan enable_shared_from_this sekarang di perpustakaan standar. Yang terakhir adalah, seperti namanya, untuk kasus ini tepat.

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

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

Contoh berdasarkan pada tautan di atas:

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

menggunakan:

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



Fungsi menerima pointer ingin melakukan salah satu dari dua perilaku:

  • Milik objeknya diteruskan, dan menghapusnya ketika keluar dari ruang lingkup. Dalam hal ini, Anda hanya dapat menerima X * dan langsung membungkus scoped_ptr di sekitar objek itu (dalam badan fungsi). Ini akan berfungsi untuk menerima "ini" atau, secara umum, setiap objek yang dialokasikan-tumpukan.
  • Bagikan pointer (jangan memilikinya) ke objek yang diteruskan. Dalam hal ini Anda lakukan tidak ingin menggunakan scoped_ptr sama sekali, karena Anda tidak ingin menghapus objek di akhir fungsi Anda. Dalam hal ini, apa yang secara teoritis Anda inginkan adalah shared_ptr (saya pernah melihatnya disebut linked_ptr di tempat lain). Perpustakaan dorongan memiliki versi shared_ptr, dan ini juga direkomendasikan dalam buku Efektif C ++ Scott Meyers (butir 18 di edisi ke-3).

Edit: Ups, saya sedikit salah membaca pertanyaan, dan sekarang saya melihat jawaban ini tidak tepat menjawab pertanyaan. Saya akan tetap membiarkannya, jika ini mungkin berguna bagi siapa saja yang bekerja pada kode yang sama.


3
2017-09-27 00:26