constexpr مقابل const في لغة C++: ما الفرق؟ دليل شامل

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

مقدمة: المعركة الأبدية للثوابت في لغة C++

\n\n

إذا كنت قد كتبت بلغة C++ من قبل (أو حتى بدأت في تعلمها)، فمن المؤكد أنك صادفت const. هذه البادئة السحرية تعد بأن قيمة المتغير لن تتغير. ولكن بعد ذلك جاء معيار C++11 وأحضر معه constexpr. وبدأ الارتباك.

\n\n

على موقع Stack Overflow، جمع سؤال "ما الفرق بين constexpr و const؟" مئات الآلاف من المشاهدات. يخلط المبرمجون من جميع المستويات بين هذين المفهومين، مستخدمين إياهما كمرادفين. لكن هذا خطأ كبير!

\n\n

في هذا البرنامج التعليمي، سنفهم مرة واحدة وإلى الأبد كيف يختلف constexpr عن const في لغة C++. ستتعلم:

\n
    \n
  • ما هو الثابت في وقت الترجمة والثابت في وقت التنفيذ.
  • \n
  • لماذا const لا يتعلق دائمًا بالأداء.
  • \n
  • كيف يحول constexpr لغة C++ إلى لغة حديثة وآمنة.
  • \n
  • متى يجب استخدام كل من هذين البناءين.
  • \n
\n\n

هيا بنا! 🚀

\n\n

الفصل 1. const: وعد وليس ضمانًا

\n\n

لنبدأ من الأساسيات. const في لغة C++ هو مؤهل نوع يخبر المترجم: "مرحبًا، لا يمكن تغيير هذه القيمة بعد التهيئة". يبدو الأمر بسيطًا، ولكن هناك فارق بسيط.

\n\n

مثال 1: const قيد التشغيل

\n\n
#include <iostream>\n\nint main() {\n    const int x = 42;  // وعد: x لن يتغير\n    // x = 100;        // خطأ في الترجمة — رائع!\n    \n    std::cout << x;   // سيطبع 42\n    return 0;\n}
\n\n

كل شيء جميل. ولكن ماذا لو تم حساب قيمة المتغير const فقط أثناء وقت التنفيذ؟

\n\n

مثال 2: const يتم حسابه في وقت التشغيل

\n\n
#include <iostream>\n\nint get_value() {\n    return 42;  // الدالة ترجع قيمة\n}\n\nint main() {\n    const int y = get_value();  // هل لا يزال const؟\n    // لكن قيمة y معروفة فقط أثناء وقت التنفيذ!\n    \n    // لنحاول استخدامه في مصفوفة:\n    // int arr[y];  // خطأ! y ليس ثابتًا في وقت الترجمة!\n    \n    return 0;\n}
\n\n

ها هو، الخدعة الرئيسية! const يحمي المتغير من التغيير، لكنه لا يضمن أن قيمته معروفة في مرحلة الترجمة. إذا تم الحصول على القيمة من دالة، فسيتم حسابها فقط عند تشغيل البرنامج.

\n\n

الاستنتاج الرئيسي: const هو عقد على عدم القابلية للتغيير، وليس على قابلية الحساب في وقت الترجمة.

\n\n

الفصل 2. constexpr: الثوابت التي تعيش في الكود

\n\n

هنا يظهر constexpr على المسرح. ظهر هذا المحدد في معيار C++11 وغيّر بشكل جذري النهج تجاه الثوابت. constexpr يعني: "يجب حساب هذه القيمة أثناء وقت الترجمة". أو، على الأقل، يمكن حسابها.

\n\n

مثال 3: متغير constexpr

\n\n
#include <iostream>\n\nint main() {\n    constexpr int z = 42;  // ضمان: القيمة معروفة في وقت الترجمة\n    \n    int arr[z];  // يعمل! z هو ثابت وقت الترجمة\n    \n    std::cout << sizeof(arr) / sizeof(arr[0]);  // سيطبع 42\n    return 0;\n}
\n\n

الفرق واضح: constexpr يسمح باستخدام المتغير في الأماكن التي يحتاج فيها المترجم إلى معرفة القيمة الدقيقة — على سبيل المثال، لحجم مصفوفة أو معاملات القوالب.

\n\n

مثال 4: دوال constexpr

\n\n

لكن الشيء الأكثر إثارة للاهتمام هو الدوال. يمكن تطبيق constexpr على الدوال، وبالتالي يمكن حسابها أثناء وقت الترجمة، إذا كانت جميع الوسائط أيضًا ثوابت وقت الترجمة.

\n\n
#include <iostream>\n\nconstexpr int square(int x) {\n    return x * x;\n}\n\nint main() {\n    constexpr int result = square(5);  // يتم حسابه في وقت الترجمة!\n    int arr[result];                   // يعمل\n    \n    std::cout << result;  // 25\n    \n    int runtime_value =                

المدونات

توصيات الكتب