Apakah mungkin untuk mengimplementasikan pointer yang sedikit cerdas yang tidak dimiliki di atas pointer lemah standar? [tertutup]

Saya telah berpikir bahwa meskipun saya memahami tujuan std::observer_ptr saya pikir itu akan terjadi alangkah baiknya jika setidaknya ada opsi untuk tipe penunjuk serupa yang mengetahui apakah yang ditunjuknya telah dihapus. Misalnya, kita dapat memiliki sesuatu seperti berikut ini

slightly_smart_ptr<Foo> p1(new Foo());
auto p2 = p1;
p1.erase(); // This deletes the foo referred to by p1.
if (p2.expired())
   std::cout << "p2 is expired\n"; // this will fire

Salah satu cara untuk mencapai hal ini dengan perpustakaan standar saat ini adalah dengan membuat shared_ptr ke A dalam beberapa cakupan yang akan ada seumur hidup A, selalu merujuk ke A dengan melewatkan Weak_ptrs di sekitar, dan menghapus A ketika tidak diperlukan lagi dengan menyetel ulang shared_ptr. Weak_ptrs di sini akan memiliki semantik dasar pengamat_ptrs yang mengetahui apakah A telah dihapus. Tetapi ada masalah dengan pendekatan ini: kelemahan_ptrs harus dikunci, mengubahnya menjadi shared_ptrs untuk digunakan, yang terasa tidak rapi, tetapi yang lebih serius adalah shared_ptrs ke A harus ada di suatu tempat, ketika yang diinginkan pengguna hanyalah penunjuk yang sedikit cerdas yang tidak dimilikinya konten apa pun. Pengguna setuju untuk menghancurkan konten secara manual ketika waktunya tiba: tidak ada kepemilikan yang dibagikan sehingga merupakan bau kode bagi pengguna untuk membuat shared_ptr dalam situasi seperti itu.

Namun saya tidak dapat memikirkan cara untuk menyembunyikan detail implementasi ini secara efektif.

Apakah penunjuk seperti itu juga ada sebagai proposal atau di perpustakaan tambahan atau di tempat lain?


person jwezorek    schedule 16.08.2019    source sumber
comment
Saya tidak yakin saya memahami pertanyaannya. Apakah Anda ingin penunjuk khusus Anda mendapat pemberitahuan saat objek yang ditunjuknya dimusnahkan, terlepas dari cara pengalokasiannya?   -  person HolyBlackCat    schedule 16.08.2019
comment
saya ingin tipe penunjuk khusus yang jika p1 dan p2 adalah turunan dari tipe keduanya menunjuk ke A, jika saya p1.reset(nullptr) ini menghapus A -- operasi ini tidak perlu disebut reset tetapi Anda mengerti -- lalu p2.expired() akan menjadi kenyataan.   -  person jwezorek    schedule 16.08.2019
comment
Kedengarannya sangat mirip dengan QPointer Qt.   -  person Jesper Juhl    schedule 16.08.2019
comment
Sulit. Sebagian besar alasan mengapa penunjuk lemah memerlukan kunci adalah agar alokasi tidak terbebas di tengah penggunaan alokasi. Jika Anda hanya ingin tahu Apakah penunjuk pada titik waktu ini valid? lalu menguncinya itu berlebihan, tapi menurut saya tidak ada gunanya alternatif lain. Alokasinya mungkin hilang segera setelah pengujian. Apakah Anda mencari pemberitahuan tentang dealokasi?   -  person user4581301    schedule 16.08.2019
comment
Saya tidak begitu melihat masalah dengan penggunaan shared_ptr dan weak_ptr. Tidak peduli bagaimana Anda mendesainnya, Anda perlu mengunci objek tersebut sehingga satu penunjuk tidak menghapusnya saat penunjuk lain menggunakannya.   -  person super    schedule 16.08.2019
comment
jika Anda hanya ingin tahu Apakah penunjuk pada titik waktu ini valid? lalu menguncinya itu berlebihan, tapi menurut saya tidak ada gunanya alternatif lain. --- Maksudku, tanpa mengunci, itu hanya berarti sedikit_smart_ptr‹T› tidak akan aman untuk thread, bukan? Namun salah satu kritik besar terhadap shared_ptr adalah Anda membayar untuk keamanan thread meskipun Anda tidak memerlukannya.   -  person jwezorek    schedule 16.08.2019
comment
@jwezorek tidak hanya itu, tapi if(ptr.valid()) { stuff(); ptr->a; } Fungsi stuff() dapat membuat pointer tidak valid, jadi Anda harus memeriksanya sebelum setiap pernyataan   -  person Guillaume Racicot    schedule 16.08.2019
comment
Apa yang Anda minta sulit-untuk-tidak mungkin dalam kasus umum, tetapi tanpa thread (dan dengan asumsi Anda tidak banyak bermain-main dengan interupsi) Anda baru saja membatasi kasus penggunaan untuk menghilangkan sebagian besar masalah yang benar-benar pelik. Saya sarankan menambahkan itu ke pertanyaan.   -  person user4581301    schedule 16.08.2019
comment
Memikirkan kembali hal itu sedikit. Ada jawaban bagus untuk pertanyaan ini berdasarkan pertanyaan seperti yang tertulis. Anda lebih baik menulis pertanyaan baru daripada membatalkannya.   -  person user4581301    schedule 16.08.2019


Jawaban (2)


Masalah dengan penunjuk pintar seperti itu adalah lebih rentan terhadap kesalahan daripada std::unique_ptr, T*, atau std::weak_ptr.

Saat Anda ingin mengetahui apakah sebuah penunjuk telah dihapus dari tempat lain oleh pemilik uniknya, pada kenyataannya Anda memerlukan kepemilikan bersama dan std::weak_ptr.

Soalnya, ada alasan mengapa Anda perlu mengunci penunjuk yang lemah sebelum menggunakannya. Itu karena ketika Anda mulai menggunakannya, Anda mendapatkan kepemilikan atas penunjuknya. Jika Anda tidak dapat mengunci penunjuk pengamat yang mengetahui apakah telah dihapus atau tidak, Anda tidak dapat menggunakannya dengan aman, karena kapan pun setelah memverifikasi keabsahannya, penunjuk tersebut dapat dihapus.


Selain itu, Anda mempunyai kontradiksi yang lebih dalam.

Jika Anda memiliki penunjuk unik, Anda tahu siapa yang akan menghapusnya, dan Anda tahu siapa pemiliknya.

Jika Anda memiliki program yang memeriksa validitas pointer saat runtime, itu karena program Anda tidak mengetahui status kepemilikan sumber daya.

Jika program Anda atau bagian dari program Anda tidak dapat mengetahui status kepemilikan sumber daya dan perlu memeriksa apakah sumber daya tersebut telah dihapus atau belum, maka Anda perlu memastikan bahwa sumber daya tersebut tidak akan terhapus pada baris berikutnya saat menggunakannya, karena itu dapat dihapus kapan saja, karena Anda tidak dapat mengetahui status kepemilikannya. Oleh karena itu, Anda perlu memiliki sumber daya sementara saat menggunakannya. Oleh karena itu, Anda memerlukan kepemilikan bersama untuk menunda keputusan kepemilikan saat menjalankan kode.

Jika Anda memiliki kepemilikan bersama, Anda tidak memerlukan penunjuk pengamat yang mengetahui apakah dihapus atau tidak.

Penunjuk Anda tidak perlu ada saat itu.


Jadi... Anda pikir Anda memerlukan penunjuk itu, mungkin berguna... apa yang dapat Anda lakukan?

Anda perlu meninjau kode Anda. Jika kepemilikannya tunggal, mengapa perlu mengetahui validitas pointernya. Mengapa Anda tidak bisa bertanya langsung kepada pemiliknya?

Jika pemiliknya tidak ada, mungkin kode Anda yang ingin dilakukan pengecekan seharusnya tidak valid ketika pemiliknya dihapus. Mungkin struktur Anda yang ingin melakukan pengecekan harus mati bersamaan dengan pemiliknya.

Jika pemilik unik Anda meninggal pada saat yang tidak terduga (misalnya, pemilik unik Anda dipegang oleh pemilik bersama), mungkin struktur Anda sebaiknya memeriksa validitas pemilik bersama.

Mungkin kode Anda yang memanggil fungsi yang ingin memeriksa apakah penunjuknya masih valid sebaiknya tidak memanggilnya ketika pemiliknya sudah mati.

...

Dan seterusnya.

Ada banyak cara untuk menyelesaikannya, tetapi memerlukan penunjuk lemah pada pemilik unik biasanya menunjukkan cacat pada program atau masalah dalam penalaran masa pakai objek dalam program Anda.

person Guillaume Racicot    schedule 16.08.2019

Secara umum tidak mungkin dilakukan.

Seluruh tujuan dari petunjuk cerdas yang masih ada adalah untuk melacak masa pakai dan kepemilikan objek dengan cara yang tidak mungkin dilakukan secara umum dengan petunjuk mentah, kecuali Anda terhubung ke pengalokasi dan memiliki hubungan berbelit-belit antara pengalokasi ini dan pegangan apa pun yang berkaitan ke objek yang dialokasikan.

Manfaat yang Anda uraikan adalah manfaat yang didapat dari penggunaan petunjuk cerdas yang masih ada tersebut. shared_ptr dan weak_ptr sempurna di sini.

Tidak ada masalah dengan penguncian (Anda menginginkan ini) dan tidak ada masalah jika harus ada shared_ptr di suatu tempat, karena pasti seseorang di suatu tempat memiliki data tersebut. Jika tidak, desain Anda memiliki masalah yang jauh lebih besar dan Anda mencoba mengatasi masalah tersebut dengan konsep penunjuk cerdas yang sama rusaknya yang tidak akan pernah ada dalam standar.

person Lightness Races in Orbit    schedule 16.08.2019