Menu
Coddy logo textTech
flag Ar iconالعربيةdown icon

المؤشرات الذكية في C++

جزء من قسم Object Oriented Programming في رحلة C++ على Coddy — الدرس 15 من 104.

المؤشرات الذكية (Smart pointers) هي فئات تغليف (wrapper classes) تدير ذاكرة الكومة (heap memory) تلقائيًا نيابة عنك. فهي تلغي الحاجة إلى استدعاءات delete اليدوية من خلال تنظيف الذاكرة عندما يخرج المؤشر عن النطاق (scope).

قم بتضمين الترويسة <memory> لاستخدام المؤشرات الذكية.

unique_ptr - الملكية الحصرية. يمكن لمؤشر واحد فقط امتلاك المورد في المرة الواحدة.

#include <memory>

std::unique_ptr<Player> player = std::make_unique<Player>("Hero");
player->attack();  // استخدمه مثل المؤشر العادي

// لا يمكن النسخ، ولكن يمكن نقل الملكية
std::unique_ptr<Player> player2 = std::move(player);
// player هو الآن nullptr

shared_ptr - ملكية مشتركة. يمكن لمؤشرات متعددة امتلاك نفس المورد. يتم تحرير الذاكرة عندما يتم تدمير آخر مالك.

std::shared_ptr<Player> p1 = std::make_shared<Player>("Hero");
std::shared_ptr<Player> p2 = p1;  // كلاهما يمتلك المورد

std::cout << p1.use_count();  // يطبع 2

weak_ptr - مراقب غير مالك لـ shared_ptr. مفيد لكسر المراجع الدائرية.

std::shared_ptr<Player> shared = std::make_shared<Player>("Hero");
std::weak_ptr<Player> weak = shared;

if (auto locked = weak.lock()) {  // تحويل إلى shared_ptr
    locked->attack();
}

استخدم unique_ptr بشكل افتراضي للملكية الفردية. استخدم shared_ptr عندما تحتاج كائنات متعددة إلى مشاركة مورد ما. استخدم weak_ptr للمراقبة دون تمديد فترة الحياة.

يفضل استخدام make_unique و make_shared بدلاً من new الخام.

challenge icon

التحدي

سهل

لنقم ببناء نظام مشاركة مستندات يوضح نماذج الملكية المختلفة للمؤشرات الذكية. سترى كيف يفرض unique_ptr الملكية الحصرية، وكيف يسمح shared_ptr بمالكين متعددين، وكيف يمكن لـ weak_ptr المراقبة دون التأثير على دورة الحياة.

ستقوم بإنشاء ملفين لتنظيم الكود الخاص بك:

  • Document.h: قم بتعريف فئة Document التي تمثل مستنداً قابلاً للمشاركة. يجب أن تحتوي على:
    • سمة title خاصة (string)
    • منشئ (constructor) يأخذ عنواناً ويطبع "Document created: <title>"
    • مدمر (destructor) يطبع "Document deleted: <title>"
    • دالة getTitle() تعيد العنوان
  • main.cpp: قم بتوضيح جميع أنواع المؤشرات الذكية الثلاثة من خلال قراءة عنوان مستند من المدخلات، ثم:
    • إنشاء unique_ptr لمستند Document بالعنوان المدخل
    • طباعة "Unique owner: <title>"
    • نقل الملكية إلى unique_ptr آخر باستخدام std::move
    • طباعة "Ownership transferred"
    • إنشاء shared_ptr لمستند Document جديد بالعنوان "SharedDoc"
    • إنشاء shared_ptr ثانٍ يشير إلى نفس المستند
    • طباعة "Shared owners: <count>" باستخدام use_count()
    • إنشاء weak_ptr من أحد المؤشرات المشتركة
    • استخدام lock() للوصول إلى المستند عبر المؤشر الضعيف وطباعة "Weak access: <title>"

تذكر تضمين <memory> للمؤشرات الذكية. استخدم std::make_unique و std::make_shared لإنشاء مؤشراتك الذكية. ستساعدك رسائل المدمر في رؤية متى يتم تنظيف كل مستند تلقائياً في نهاية البرنامج.

قم بتضمين ملف الرأس الخاص بك في main.cpp باستخدام #include "Document.h".

ورقة مرجعية

المؤشرات الذكية (Smart pointers) هي فئات مغلفة تدير ذاكرة الكومة (heap memory) تلقائياً. قم بتضمين الترويسة <memory> لاستخدامها.

unique_ptr

ملكية حصرية - يمكن لمؤشر واحد فقط امتلاك المورد في المرة الواحدة:

std::unique_ptr<Player> player = std::make_unique<Player>("Hero");
player->attack();  // استخدمه مثل المؤشر العادي

// نقل الملكية باستخدام std::move
std::unique_ptr<Player> player2 = std::move(player);
// player هو الآن nullptr

shared_ptr

ملكية مشتركة - يمكن لعدة مؤشرات امتلاك نفس المورد. يتم تحرير الذاكرة عند تدمير آخر مالك:

std::shared_ptr<Player> p1 = std::make_shared<Player>("Hero");
std::shared_ptr<Player> p2 = p1;  // كلاهما يمتلك المورد

std::cout << p1.use_count();  // يطبع 2

weak_ptr

مراقب غير مالك لـ shared_ptr. مفيد لكسر المراجع الدائرية:

std::shared_ptr<Player> shared = std::make_shared<Player>("Hero");
std::weak_ptr<Player> weak = shared;

if (auto locked = weak.lock()) {  // التحويل إلى shared_ptr
    locked->attack();
}

أفضل الممارسات: استخدم unique_ptr بشكل افتراضي للملكية الفردية. استخدم shared_ptr عندما تحتاج كائنات متعددة لمشاركة مورد ما. استخدم weak_ptr للمراقبة دون تمديد فترة الحياة. فضل استخدام make_unique و make_shared على new الخام.

جرّب بنفسك

#include <iostream>
#include <memory>
#include <string>
#include "Document.h"

using namespace std;

int main() {
    string inputTitle;
    cin >> inputTitle;

    // TODO: قم بإنشاء unique_ptr لـ Document باستخدام inputTitle
    // باستخدام std::make_unique

    // TODO: اطبع "Unique owner: <title>"

    // TODO: انقل الملكية إلى unique_ptr آخر باستخدام std::move

    // TODO: اطبع "Ownership transferred"

    // TODO: قم بإنشاء shared_ptr لـ Document جديد بالعنوان "SharedDoc"
    // باستخدام std::make_shared

    // TODO: قم بإنشاء shared_ptr ثانٍ يشير إلى نفس المستند

    // TODO: اطبع "Shared owners: <count>" باستخدام use_count()

    // TODO: قم بإنشاء weak_ptr من أحد المؤشرات المشتركة (shared pointers)

    // TODO: استخدم lock() للوصول إلى المستند من خلال weak_ptr
    // واطبع "Weak access: <title>"

    return 0;
}
quiz iconاختبر نفسك

يتضمن هذا الدرس اختبارًا قصيرًا. ابدأ الدرس للإجابة عليه وتتبّع تقدمك.

جميع دروس Object Oriented Programming