Saat ini saya mencoba mempelajari cara menggunakan petunjuk cerdas. Namun saat melakukan beberapa eksperimen, saya menemukan situasi berikut yang tidak dapat saya temukan solusi yang memuaskan:
Bayangkan Anda memiliki objek kelas A menjadi induk dari objek kelas B (anak), tetapi keduanya harus saling mengenal:
class A;
class B;
class A
{
public:
void addChild(std::shared_ptr<B> child)
{
children->push_back(child);
// How to do pass the pointer correctly?
// child->setParent(this); // wrong
// ^^^^
}
private:
std::list<std::shared_ptr<B>> children;
};
class B
{
public:
setParent(std::shared_ptr<A> parent)
{
this->parent = parent;
};
private:
std::shared_ptr<A> parent;
};
Pertanyaannya adalah bagaimana objek kelas A meneruskan a std::shared_ptr
dari dirinya sendiri ( this
) ke anaknya?
Ada solusi untuk Boost shared pointer ( Mendapatkan boost::shared_ptr
untukthis
), tetapi bagaimana menangani ini menggunakan std::
smart pointer?
c++
this
shared-ptr
this-pointer
Icarus
sumber
sumber
Jawaban:
Ada
std::enable_shared_from_this
hanya untuk tujuan ini. Anda mewarisinya dan Anda dapat menelepon.shared_from_this()
dari dalam kelas. Selain itu, Anda membuat dependensi melingkar di sini yang dapat menyebabkan kebocoran resource. Itu bisa diatasi dengan penggunaanstd::weak_ptr
. Jadi kode Anda mungkin terlihat seperti ini (dengan asumsi anak-anak bergantung pada keberadaan induk dan bukan sebaliknya):Namun perlu dicatat, bahwa panggilan
.shared_from_this()
membutuhkan yangthis
dimiliki olehstd::shared_ptr
saat menelepon. Ini berarti bahwa Anda tidak dapat membuat objek seperti itu di tumpukan lagi, dan umumnya tidak dapat memanggil.shared_from_this()
dari dalam konstruktor atau destruktor.sumber
shared_ptr
berdasarkan yang dibangun secara defaultshared_ptr
dan apa pun yang Anda ingin tunjukkan ...shared_ptr
ini tidak relevan dengan pertanyaan ini.shared_from_this
Prasyarat dengan jelas menyatakan bahwa objek harus dimiliki (tidak hanya ditunjuk) oleh beberapa orangshared_ptr
pada titik panggilan.shared_ptr
diperlukan pada saat panggilan, tetapi dalam pola penggunaan tipikal, misalnyashared_ptr<Foo> p(new Foo());
,shared_ptr
mengambil kepemilikan objek hanya setelah itu sepenuhnya dibangun. Hal ini dimungkinkan untuk menghindari ini dengan membuatshared_ptr
dalam konstruktor yang diinisialisasi denganthis
dan menyimpannya di suatu tempat non-lokal (misalnya dalam argumen referensi) sehingga tidak mati ketika konstruktor selesai. Tetapi skenario yang berbelit-belit ini sepertinya tidak diperlukan.Anda memiliki beberapa masalah dalam desain Anda, yang tampaknya berasal dari kesalahpahaman Anda tentang petunjuk cerdas.
Pointer cerdas digunakan untuk menyatakan kepemilikan. Anda memecahkan ini dengan menyatakan bahwa kedua orang tua memiliki semua anak, tetapi juga bahwa setiap anak memiliki orang tuanya. Keduanya tidak mungkin benar.
Selain itu, Anda mengembalikan penunjuk lemah ke dalam
getChild()
. Dengan demikian, Anda menyatakan bahwa penelepon tidak boleh peduli dengan kepemilikan. Sekarang ini bisa sangat membatasi, tetapi juga dengan melakukan itu, Anda harus memastikan bahwa anak yang dimaksud tidak akan dihancurkan sementara petunjuk lemah masih dipegang, jika Anda akan menggunakan penunjuk cerdas, itu akan diselesaikan dengan sendirinya .Dan hal terakhir. Biasanya, saat Anda menerima entitas baru, Anda biasanya harus menerima petunjuk mentah. Pointer cerdas dapat memiliki arti sendiri untuk menukar anak di antara orang tua, tetapi untuk penggunaan umum, Anda harus menerima petunjuk mentah.
sumber