std::weak_ptr
المؤشّر الضعيف std::weak_ptr
std::weak_ptr يراقب كائنًا يملكه shared_ptr دون زيادة عدّاد المراجع — يكسر دورات المراجع التي تسبب تسريب ذاكرة.
لو كان كائنان من نوع shared_ptr يشير كل منهما للآخر (دورة مراجع)، فعدّاد المراجع لن يصل للصفر أبدًا حتى لو لم يعد أحد بالبرنامج يستخدمهما — تسريب ذاكرة صامت. weak_ptr يحل هذا: يشير للكائن نفسه لكن بدون زيادة العدّاد، فلا يمنع تحريره. للوصول الفعلي للكائن يجب تحويله مؤقتًا لـ shared_ptr عبر lock()، الذي يُرجع مؤشّرًا فارغًا لو كان الكائن قد تحرّر فعلًا.
الصياغة
std::weak_ptr<Type> w = sharedPtr;
if (auto locked = w.lock()) { /* استخدم locked */ }📄 مثال
struct Node {
std::shared_ptr<Node> next;
std::weak_ptr<Node> prev; // weak لكسر الدورة
};
auto a = std::make_shared<Node>();
auto b = std::make_shared<Node>();
a->next = b;
b->prev = a; // weak — لا يزيد عدّاد a
if (auto p = b->prev.lock()) {
std::cout << "الأب ما زال موجودًا";
}أهم النقاط
| العنصر | الوظيفة |
|---|---|
| lock() | يحاول إرجاع shared_ptr صالح؛ يُرجع مؤشّرًا فارغًا لو تحرّر الكائن أصلًا |
| expired() | فحص سريع إن كان الكائن المُشار إليه قد تحرّر بالفعل |
| بدون تأثير على العدّاد | إنشاء أو حذف weak_ptr لا يغيّر عدّاد مراجع shared_ptr إطلاقًا |
💡 نصائح عملية
- استخدمه دائمًا للطرف «الخلفي» بعلاقة ثنائية الاتجاه (parent/child، next/prev) لمنع دورة مراجع
- تحقق دائمًا من ناتج lock() قبل الاستخدام — قد يكون الكائن قد تحرّر فعلًا
⚠️ أخطاء شائعة
- استخدام shared_ptr بالاتجاهين بعلاقة دائرية بدل weak_ptr بأحدهما — يسبب تسريب ذاكرة صامت لا يظهر إلا بمراقبة الاستهلاك
- استخدام الكائن مباشرة عبر weak_ptr بدون lock() أولًا — weak_ptr لا يوفّر وصولًا مباشرًا للكائن أصلًا
خصائص ذات صلة
🎓 تريد فهم الصورة الكاملة خطوة بخطوة؟ ابدأ من مسار CPP الكامل بالعربي.