const مع المؤشرات — المؤشرات والذاكرة
const مع المؤشرات
const مع المؤشرات لها موقعان، ولكل منهما معنى مختلف. اقرأ التصريح من اليمين إلى اليسار.
1) مؤشر إلى ثابت: لا تعدّل القيمة
int x = 1, y = 2;
const int* p = &x; // "p مؤشر إلى int ثابت"
*p = 5; // ❌ لا يمكن تعديل القيمة عبر p
p = &y; // ✅ يمكن توجيهه لمتغير آخرالأكثر استخداماً: معاملات الدوال التي تقرأ فقط: int sum(const int* arr, int size). يضمن للمستدعي أن الدالة لن تغيّر بياناته.
2) مؤشر ثابت: لا تغيّر العنوان
int* const p = &x; // "p مؤشر ثابت إلى int"
*p = 5; // ✅ تعديل القيمة مسموح
p = &y; // ❌ لا يمكن توجيهه لمكان آخريجب تهيئته عند الإنشاء.
3) الاثنان معاً
int x = 1;
const int* const p = &x; // لا تعديل للقيمة ولا للعنوانطريقة التذكر
| التصريح | القيمة | العنوان |
|---|---|---|
| const int* p (أو int const* p) | ثابتة | متغير |
| int* const p | متغيرة | ثابت |
| const int* const p | ثابتة | ثابت |
const قبل النجمة تحمي القيمة، و بعدها تحمي المؤشر نفسه.
const-correctness
"صحة const" عادة احترافية: ضع const على كل ما لا يجب أن يتغير (معاملات، دوال الأصناف التي لا تعدّل الكائن). المترجم يكتشف عندها محاولات التعديل الخاطئة، ويصبح الكود أوضح لمن يقرأه.
نفس الفكرة مع المراجع
const T& (من دورة الأساسيات) هي النسخة الأكثر استخداماً من "مؤشر إلى ثابت".
⚠️ const_cast
توجد طريقة لإزالة const، لكن تعديل كائن كان const أصلاً سلوك غير معرّف. إذا احتجت const_cast فغالباً التصميم يحتاج مراجعة.
تمرين
اكتب int findMax(const int* arr, int size)، وحاول داخلها تعديل عنصر ولاحظ خطأ المترجم. ثم أنشئ int* const cursor وحاول تحريكه ولاحظ الخطأ.
#include <iostream>
using namespace std;
void printValue(const int* ptr) {
// *ptr = 10; // خطأ! لا يمكن التعديل
cout << "القيمة: " << *ptr << endl;
}
int main() {
int x = 10;
int y = 20;
// ===== 1. Pointer to const =====
// القيمة ثابتة، العنوان يتغير
const int* ptr1 = &x;
cout << "ptr1 يشير لـ: " << *ptr1 << endl;
// *ptr1 = 50; // خطأ! لا يمكن تغيير القيمة
ptr1 = &y; // يعمل! تغيير العنوان
cout << "ptr1 الآن يشير لـ: " << *ptr1 << endl;
// ===== 2. Const pointer =====
// العنوان ثابت، القيمة تتغير
int* const ptr2 = &x;
cout << "\nptr2 يشير لـ: " << *ptr2 << endl;
*ptr2 = 100; // يعمل! تغيير القيمة
// ptr2 = &y; // خطأ! لا يمكن تغيير العنوان
cout << "x بعد التعديل: " << x << endl;
// ===== 3. Const pointer to const =====
// لا شيء يتغير
const int* const ptr3 = &x;
cout << "\nptr3 يشير لـ: " << *ptr3 << endl;
// *ptr3 = 50; // خطأ!
// ptr3 = &y; // خطأ!
// ===== استخدام عملي =====
int arr[] = {1, 2, 3, 4, 5};
int size = 5;
// دالة تقرأ فقط - تستخدم const
cout << "\nالمصفوفة: ";
for (const int* p = arr; p < arr + size; p++) {
cout << *p << " ";
// *p = 0; // ممنوع!
}
cout << endl;
// دالة تعدل - بدون const
cout << "بعد المضاعفة: ";
for (int* p = arr; p < arr + size; p++) {
*p *= 2; // مسموح
cout << *p << " ";
}
cout << endl;
// ===== مع الدوال =====
int num = 42;
printValue(&num); // الدالة لن تعدل القيمة
// ===== ملخص =====
cout << "\n=== ملخص ===" << endl;
cout << "const int* ptr → القيمة ثابتة" << endl;
cout << "int* const ptr → العنوان ثابت" << endl;
cout << "const int* const → كلاهما ثابت" << endl;
return 0;
}اختبر فهمك