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

١٦ يوليو ٢٠٢٦

ما هو RAII في C++ بالعربي؟

شارك المقال:

RAII اختصار لـ Resource Acquisition Is Initialization — أهم مبدأ تصميم في C++ للتعامل الآمن مع أي مورد محدود، ومصدر الأمان وراء أدوات مثل unique_ptr وlock_guard.

المشكلة التي يحلّها RAII

بدون RAII، إدارة مورد مثل الذاكرة أو الملف تعتمد على تذكّرك اليدوي للتحرير في كل مسار ممكن بالكود:

void riskyFunction() {
    FILE* f = fopen("data.txt", "r");

    if (someErrorCondition()) {
        return; // ❌ تسريب! نسينا fclose هنا
    }

    processFile(f); // لو رمت هذه استثناءً، fclose التالي لن يُنفَّذ أبدًا

    fclose(f);
}

كل نقطة خروج محتملة (return مبكّر، استثناء) تحتاج تذكّرًا يدويًا للتحرير — وهذا عرضة للنسيان بمشاريع كبيرة.

فكرة RAII

اربط عمر المورد بعمر كائن: احجزه بالباني (constructor)، وحرّره بالهادم (destructor). لما يخرج الكائن من نطاقه — طبيعيًا أو بسبب استثناء — يُستدعى الهادم تلقائيًا:

class FileHandle {
    FILE* f;
public:
    FileHandle(const char* path) {
        f = fopen(path, "r"); // حجز المورد بالباني
    }
    ~FileHandle() {
        if (f) fclose(f);     // تحرير المورد بالهادم — دائمًا يُنفَّذ
    }
};

void safeFunction() {
    FileHandle file("data.txt");

    if (someErrorCondition()) {
        return; // ✅ الهادم يُستدعى تلقائيًا هنا، الملف يُغلق دائمًا
    }

    processFile(file);
} // ✅ إغلاق تلقائي هنا أيضًا مهما حدث

لا حاجة لتذكّر أي شيء — الهادم يعمل دائمًا، بضمان اللغة نفسها.

أمثلة RAII بالمكتبة القياسية

معظم أدوات C++ الحديثة الآمنة هي فعليًا كائنات RAII:

الكائنالمورد المُدار
std::unique_ptr / std::shared_ptrذاكرة على الكومة
std::vector / std::stringذاكرة داخلية ديناميكية
std::lock_guardقفل mutex
std::ifstream / std::ofstreamمقبض ملف

مثال lock_guard — أهم استخدام في البرمجة المتزامنة:

#include <mutex>

std::mutex mtx;
int counter = 0;

void increment() {
    std::lock_guard<std::mutex> lock(mtx); // يقفل هنا
    counter++;
} // يفكّ القفل تلقائيًا هنا — يستحيل نسيان فكّه حتى مع استثناء

RAII مقابل جامع القمامة

لغات مثل Java وPython تحل مشكلة الذاكرة بجامع قمامة (Garbage Collector) يعمل بالخلفية. C++ لا تملك جامع قمامة بشكل افتراضي، فـ RAII هو الحل المكافئ — وميزته أنه يعمم الفكرة لأي مورد، لا الذاكرة فقط: أقفال، اتصالات، مقابض ملفات، كلها تستفيد من نفس المبدأ بلا انتظار دورة تنظيف لاحقة.

الخلاصة

RAII ليس ميزة لغوية منفصلة بل نمط استخدام لباني وهادم الصنف. أي مرة تدير موردًا يدويًا بكودك، اسأل نفسك: هل يمكن تغليفه بكائن يحرّره تلقائيًا؟ الجواب غالبًا نعم — وهذا بالضبط سرّ أمان C++ الحديثة رغم غياب جامع القمامة.

اقرأ أكثر عن المؤشّرات الذكية والذاكرة الديناميكية في مسار C++ الكامل.

📚 مصادر رسمية للتعمّق: مرجع C++ الرسمي

الأسئلة الشائعة

هل RAII خاص فقط بإدارة الذاكرة؟

لا. RAII مبدأ عام لأي مورد محدود يحتاج تحريرًا: ذاكرة، ملفّات، أقفال (mutex)، اتصالات شبكة أو قواعد بيانات. أي مورد يحتاج فتحًا وإغلاقًا هو مرشّح لـ RAII.

ما علاقة RAII بـ unique_ptr وshared_ptr؟

المؤشّرات الذكية أشهر تطبيق عملي لـ RAII: تحجز الذاكرة بالباني وتحرّرها بالهادم تلقائيًا، فتتخلّص من الحاجة لـ new/delete اليدوية.

هل لغات مثل Java وPython تحتاج RAII؟

ليس بنفس الشكل — تلك اللغات فيها جامع قمامة (Garbage Collector) يحرّر الذاكرة تلقائيًا. RAII حل C++ الخاص لأنها لا تملك جامع قمامة، ويمتد ليشمل موارد غير الذاكرة أيضًا.

اقرأ أيضًا

تصفّح كل المقالات في المدوّنة، أو ابدأ التعلّم من المسارات و خرائط الطريق.