دروس الوحدة (2/2)
الأمراض المنقولة جنسيا::weak_ptr
على الرغم من أن std::shared_ptr مفيد للغاية، إلا أن الاعتماد فقط على الملكية المشتركة يمكن أن يؤدي إلى مشكلة تُعرف باسم المرجع الدائري (أو التبعية الدورية).
إذا كان كل كائنين أو أكثر يحتوي كل منهما على shared_ptr يشير إلى الآخر، فسيتم إنشاء حلقة مغلقة. في هذه الحالة، لن يصل العدد المرجعي لأي من الكائنين إلى الصفر، مما يمنع إلغاء التخصيص ويتسبب في حدوث تسرب للذاكرة.
ما هو محمي_INLINE_2
لكسر دورات الملكية، توفر المكتبة القياسية std::weak_ptr. هذا مؤشر ذكي يراقب كائنًا تتم إدارته بواسطة shared_ptr، ولكن بدون زيادة عدد المرجع.
وهي لا تمتلك المورد بشكل مباشر، وبالتالي لا تمنع تدميره.
#include <memory>
std::shared_ptr<int> shared = std::make_shared<int>(42);
std::weak_ptr<int> weak = shared; // Does not increment reference count!التحقق من المصدر والوصول إليه
نظرًا لأن weak_ptr لا يمتلك المورد، فمن الممكن إلغاء تخصيص المورد في أي وقت (عندما تخرج جميع مثيلات shared_ptr المرتبطة خارج النطاق).
لاستخدام المورد المرصود، يجب علينا:
- تحقق مما إذا كانت لا تزال صالحة باستخدام
expired(). - قم بتحويل
weak_ptrمؤقتًا إلىshared_ptrباستخدام الطريقةlock(). إذا كان المورد لا يزال نشطًا، فإنlock()يُرجعshared_ptrصالحًا، وإلا فإنه يُرجع مؤشرًا فارغًا (nullptr).
if (!weak.expired()) {
// lock() creates a temporary shared_ptr to ensure safe access
if (std::shared_ptr<int> sharedAccess = weak.lock()) {
std::cout << *sharedAccess << std::endl;
}
} else {
std::cout << "Resource deallocated!" << std::endl;
}جربه بنفسك
قم بتعريف std::weak_ptr<int> المسمى wPtr الذي تمت تهيئته من sPtr. ثم قم بطباعة النتيجة المنطقية التي تم إرجاعها بواسطة wPtr.expired() باستخدام std::cout.
إظهار التلميح
قم بتعريف `weak_ptr` الذي يشير إلى نفس النوع العام `<int>` وقم بتعيين `sPtr` إليه مباشرةً.
الحل متاح بعد 3 من المحاولات
استخدم طريقة lock() على wPtr للحصول على Shared_ptr مؤقت. إذا نجحت العملية (المؤشر ليس فارغًا)، فاطبع القيمة التي تم إلغاء الإشارة إليها.
إظهار التلميح
قم بتهيئة متغير داخل كتلة `if` عن طريق استدعاء `wPtr.lock()`، ثم اطبع المورد وألغي الإشارة إليه باستخدام العلامة النجمية `*`.
الحل متاح بعد 3 من المحاولات