English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
لدي كل متغير في C++ خاصيتين: النوع والمصنف
يُحدد النوع نوع البيانات التي يمكن تخزينها في المتغير. على سبيل المثال: int،float،char وما إلى ذلك.
كما يُتحكم مصنف التخزين في سمتين مختلفتين من المتغيرات: مدة الحياة (تحدد مدة وجود المتغير) ومدى التغطية (تحدد أجزاء البرنامج التي يمكن الوصول إليها)
يُحدد مصنف التخزين نطاق المتغيرات/الدوال (الرؤية) ومدة حياتها في برنامج C++. يتم وضع هذه المُؤشرات قبل النوع الذي يتم تعديلهما. يُظهر أدناه مصنفات التخزين المتاحة في برنامج C++:
auto
register
static
extern
mutable
thread_local (C++11)
منذ بداية C++ 17، لم يعد مفتاح auto مُؤشرًا على مصنف التخزين في C++، وأصبح مفتاح register مستخدماً
منذ C++ 11،auto يُستخدم المفتاح كلمات في حالتين: عند تعريف المتغير بناءً على تعبير التوليد تلقائيًا، عند تعريف الدالة كحل محل قيمة العودة.
يُستخدم مفتاح auto للكلمات المُتغيرات في معيار C++98، ولكن تم حذف هذا الاستخدام بسبب قلة الاستخدام والزائدة في C++11.
يُفترض نوع المتغير المُعلن تلقائيًا بناءً على تعبير التوليد، مثل:
auto f=3.14; // double auto s("hello"); // const char* auto z = new auto(9); // int* auto x1 = 5, x2 = 5.0, x3='r'; // خطأ، يجب أن يتم تعريفها بشكل مسبق لنفس النوع
register يُستخدم مصنف التخزين لتحديد المتغيرات المحلية التي يتم تخزينها في السجل بدلاً من RAM. مما يعني أن حجم المتغيرات القصوى يساوي حجم السجل (عادة كلمة واحدة) ولا يمكن تطبيق عمليات حسابية سلبية على ذلك (بما أن لديه موقع ذاكرة)
{ register int miles; {}
يُستخدم سجل فقط للمتغيرات التي تحتاج إلى الوصول السريع، مثل المحتسب. يجب أن يتم ملاحظة أيضًا أن تعريف 'register' لا يعني أن المتغير سيتم تخزينه في السجل، بل يعني أن المتغير قد يتم تخزينه في السجل، اعتمادًا على القيود على الأجهزة والتنفيذ.
static يُشير مُؤشر التخزين إلى مُكتبة التجميع في دورة حياة البرنامج الحالية للحفاظ على وجود المتغيرات المحلية، دون الحاجة إلى إنشاء وإزالة كل مرة يدخل فيها النطاق أو يخرج منه. لذلك، يمكن استخدام مُعزز static للحفاظ على قيمة المتغيرات المحلية بين دعوات الدوال.
يمكن تطبيق ميزة static أيضًا على المتغيرات العالمية.عندما يتم تطبيق static على متغير عالمي،سيؤدي إلى تقييد نطاق المتغير إلى ملف الاشارة إليه.
في C++،عندما يتم استخدام static مع عضو البيانات الكائن،سيؤدي إلى أن يكون هناك نسخة واحدة فقط من هذا العضو يتم مشاركتها بين جميع كائنات الكائن.
#include <iostream> // إعلان الدالة void func(void); static int count = 25; /* متغير عالمي */ int main() { while(count--) { func(); {} return 0; {} // تعريف الدالة void func(void) { static int i = 8; // متغير استاتيك محلي i++; std::cout << "المغير i هو " << i; std::cout << "،المغير count هو " << count << std::endl; {}
عندما يتم تجميع وتنفيذ الكود المشار إليه،سيتم إنتاج النتيجة التالية:
المغير i هو 9،المغير count هو 24 المغير i هو 10،المغير count هو 23 المغير i هو 11،المغير count هو 22 المغير i هو 12،المغير count هو 21 المغير i هو 13،المغير count هو 20 المغير i هو 14،المغير count هو 19 المغير i هو 15،المغير count هو 18 المغير i هو 16،المغير count هو 17 المغير i هو 17،المغير count هو 16 المغير i هو 18،المغير count هو 15 المغير i هو 19،المغير count هو 14 المغير i هو 20،المغير count هو 13 المغير i هو 21،المغير count هو 12 المغير i هو 22،المغير count هو 11 المغير i هو 23،المغير count هو 10 المغير i هو 24،المغير count هو 9 المغير i هو 25،المغير count هو 8 المغير i هو 26،المغير count هو 7 المغير i هو 27،المغير count هو 6 المغير i هو 28،المغير count هو 5 المغير i هو 29،المغير count هو 4 المغير i هو 30،المغير count هو 3 المغير i هو 31،المغير count هو 2 المتغير i هو 32، المتغير count هو 1 المتغير i هو 33، المتغير count هو 0
extern نوع التخزين يستخدم لتقديم مرجع إلى المتغيرات العالمية، المتغيرات العالمية تكون مرئية لجميع ملفات البرنامج. عند استخدام 'extern'، سيتم توجيه اسم المتغير إلى موقع التخزين المحدد مسبقًا للاشارة إلى المتغيرات التي لا يمكن تحديد قيمتها.
عندما يكون لديك عدة ملفات وقد قمت بتعريف متغير أو دالة يمكن استخدامها في ملفات أخرى، يمكنك استخدامها في ملفات أخرى extern للحصول على مرجع إلى المتغيرات أو الدوال المحددة مسبقًا. يمكن فهم ذلك كالتالي،extern لإعلان متغير عالمي أو دالة في ملف آخر.
ميزة extern تستخدم عادةً عندما يكون هناك ملفان أو أكثر يتشاركون نفس المتغيرات العالمية أو الدوال، مثلما يلي:
الملف الأول: main.cpp
#include <iostream> int count; extern void write_extern(); int main() { count = 5; write_extern(); {}
الملف الثاني: support.cpp
#include <iostream> extern int count; void write_extern(void) { std::cout << "Count is " << count << std::endl; {}
في هذا المكان، الملف الثاني extern كلمة مفتاحية تستخدم لتحديد المتغيرات التي تم تعريفها مسبقًا في الملف الأول main.cpp. الآن، قم بتشغيل هذين الملفين كما يلي:
$ g++ main.cpp support.cpp -o write
سيكون لدينا write برنامج قابل للتنفيذ، محاولة تنفيذه write، وسيكون لدينا النتيجة التالية:
$ ./write Count is 5
mutable تطبيق ميزة thread_local يكون فقط مناسبًا لأعضاء الكائنات للفئات، سيتم شرح ذلك في نهاية هذا الدليل. يسمح ذلك للأعضاء المتغيرين بتبديل الأعضاء الثابتة. أي أن يمكن تعديل الأعضاء المتغيرة من خلال الدوال الثابتة.
يمكن الوصول إلى المتغيرات المعلنة باستخدام ميزة thread_local فقط في الخطوة التي تم إنشاؤها فيها. يتم إنشاء المتغير عند إنشاء الخطوة، ويتم إزالته عند إزالة الخطوة. يحتوي كل خطوة على نسخة من المتغير الخاصة بها.
يمكن دمج ميزة thread_local مع static أو extern.
يمكن تطبيق thread_local فقط على إعلان وتعريف البيانات، thread_local لا يمكن استخدامها في إعلان أو تعريف الدوال.
يُظهر هذا المثال المتغيرات التي يمكن إعلانها كـ thread_local:
thread_local int x; // متغيرات العالمية في المساحة class X { static thread_local std::string s; // متغيرات العضو الثابتة للفئة }; static thread_local std::string X::s; // X::s يجب أن يتم تعريفها void foo() { thread_local std::vector<int> v; // متغير محلي {}