تخطَّ إلى المحتوى

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 الكامل بالعربي.