Cara: Membuat dan menggunakan instans weak_ptr
Terkadang objek harus menyimpan cara untuk mengakses objek yang mendasar dari shared_ptr tanpa menyebabkan jumlah referensi bertambah. Biasanya, situasi ini terjadi ketika Anda memiliki referensi siklik antar shared_ptr
instans.
Desain terbaik adalah menghindari kepemilikan pointer bersama kapan pun Anda bisa. Namun, jika Anda harus memiliki kepemilikan shared_ptr
instans bersama, hindari referensi siklik di antaranya. Ketika referensi siklik tidak dapat ditolak, atau bahkan lebih disukai karena alasan tertentu, gunakan weak_ptr untuk memberi satu atau beberapa pemilik referensi lemah ke yang lain shared_ptr
. Dengan menggunakan weak_ptr
, Anda dapat membuat shared_ptr
yang bergabung ke sekumpulan instans terkait yang ada, tetapi hanya jika sumber daya memori yang mendasar masih valid. Itu weak_ptr
sendiri tidak berpartisipasi dalam penghitungan referensi, dan oleh karena itu, itu tidak dapat mencegah jumlah referensi masuk ke nol. Namun, Anda dapat menggunakan weak_ptr
untuk mencoba mendapatkan salinan shared_ptr
baru yang diinisialisasi. Jika memori telah dihapus, weak_ptr
operator bool akan mengembalikan false
. Jika memori masih valid, penunjuk bersama baru menaikkan jumlah referensi dan menjamin bahwa memori akan valid selama shared_ptr
variabel tetap berada dalam cakupan.
Contoh
Contoh kode berikut menunjukkan kasus di mana weak_ptr
digunakan untuk memastikan penghapusan objek yang tepat yang memiliki dependensi melingkar. Saat Anda memeriksa contoh, asumsikan bahwa itu dibuat hanya setelah solusi alternatif dipertimbangkan. Objek Controller
mewakili beberapa aspek proses mesin, dan mereka beroperasi secara independen. Setiap pengontrol harus dapat mengkueri status pengontrol lain kapan saja, dan masing-masing berisi privat vector<weak_ptr<Controller>>
untuk tujuan ini. Setiap vektor berisi referensi melingkar, dan oleh karena itu, weak_ptr
instans digunakan alih-alih shared_ptr
.
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
class Controller
{
public:
int Num;
wstring Status;
vector<weak_ptr<Controller>> others;
explicit Controller(int i) : Num(i), Status(L"On")
{
wcout << L"Creating Controller" << Num << endl;
}
~Controller()
{
wcout << L"Destroying Controller" << Num << endl;
}
// Demonstrates how to test whether the
// pointed-to memory still exists or not.
void CheckStatuses() const
{
for_each(others.begin(), others.end(), [](weak_ptr<Controller> wp) {
auto p = wp.lock();
if (p)
{
wcout << L"Status of " << p->Num << " = " << p->Status << endl;
}
else
{
wcout << L"Null object" << endl;
}
});
}
};
void RunTest()
{
vector<shared_ptr<Controller>> v{
make_shared<Controller>(0),
make_shared<Controller>(1),
make_shared<Controller>(2),
make_shared<Controller>(3),
make_shared<Controller>(4),
};
// Each controller depends on all others not being deleted.
// Give each controller a pointer to all the others.
for (int i = 0; i < v.size(); ++i)
{
for_each(v.begin(), v.end(), [&v, i](shared_ptr<Controller> p) {
if (p->Num != i)
{
v[i]->others.push_back(weak_ptr<Controller>(p));
wcout << L"push_back to v[" << i << "]: " << p->Num << endl;
}
});
}
for_each(v.begin(), v.end(), [](shared_ptr<Controller> &p) {
wcout << L"use_count = " << p.use_count() << endl;
p->CheckStatuses();
});
}
int main()
{
RunTest();
wcout << L"Press any key" << endl;
char ch;
cin.getline(&ch, 1);
}
Creating Controller0
Creating Controller1
Creating Controller2
Creating Controller3
Creating Controller4
push_back to v[0]: 1
push_back to v[0]: 2
push_back to v[0]: 3
push_back to v[0]: 4
push_back to v[1]: 0
push_back to v[1]: 2
push_back to v[1]: 3
push_back to v[1]: 4
push_back to v[2]: 0
push_back to v[2]: 1
push_back to v[2]: 3
push_back to v[2]: 4
push_back to v[3]: 0
push_back to v[3]: 1
push_back to v[3]: 2
push_back to v[3]: 4
push_back to v[4]: 0
push_back to v[4]: 1
push_back to v[4]: 2
push_back to v[4]: 3
use_count = 1
Status of 1 = On
Status of 2 = On
Status of 3 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 2 = On
Status of 3 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 1 = On
Status of 3 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 1 = On
Status of 2 = On
Status of 4 = On
use_count = 1
Status of 0 = On
Status of 1 = On
Status of 2 = On
Status of 3 = On
Destroying Controller0
Destroying Controller1
Destroying Controller2
Destroying Controller3
Destroying Controller4
Press any key
Sebagai eksperimen, ubah vektor others
menjadi vector<shared_ptr<Controller>>
, dan kemudian dalam output, perhatikan bahwa tidak ada destruktor yang dipanggil saat RunTest
kembali.
Baca juga
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk