المؤشرات والدوال — المؤشرات والذاكرة
المؤشرات والدوال
تمرير مؤشر لدالة
void addBonus(int* score, int bonus) {
if (score == nullptr) return; // افحص دائماً
*score += bonus;
}
int s = 70;
addBonus(&s, 10); // نمرر العنوانالنتيجة مثل التمرير بالمرجع int&، لكن مع فرقين:
- المستدعي يكتب &s، فيكون واضحاً في مكان الاستدعاء أن المتغير قد يتغير.
- يمكن تمرير nullptr لتعني "لا يوجد"، فيجب على الدالة الفحص.
متى تختار المؤشر بدل المرجع؟
| استخدم T& | استخدم T* |
|---|---|
| المعامل إلزامي دائماً | المعامل اختياري (قد يكون nullptr) |
| الكود الحديث العادي | واجهات مكتبات C، أو "معامل إخراج اختياري" |
إرجاع مؤشر
int* findFirstNegative(int* arr, int size) {
for (int i = 0; i < size; i++)
if (arr[i] < 0) return &arr[i];
return nullptr; // لم يوجد
}إرجاع nullptr طريقة شائعة لقول "لم أجد".
⚠️ لا ترجع عنوان متغير محلي
int* bad() {
int local = 5;
return &local; // local يُدمَّر عند انتهاء الدالة
}المؤشر الناتج معلّق (dangling): يشير لذاكرة لم تعد صالحة. المترجم يحذر أحياناً فقط. ستفهم السبب بالتفصيل في درس Stack و Heap.
مؤشرات إلى دوال (نظرة)
int (*op)(int, int) = add; مؤشر يحمل عنوان دالة، ويُستدعى op(2, 3). في C++ الحديثة تُستخدم بدلها غالباً std::function أو lambdas (الدورة المتقدمة).
تمرين
اكتب bool divide(int a, int b, int* result) ترجع false عند القسمة على صفر، وتكتب الناتج في *result فقط إذا لم يكن result فارغاً. ثم اكتب نسخة بالمرجع وقارن.
#include <iostream>
using namespace std;
// By Value - لا يغير الأصل
void incrementByValue(int x) {
x++;
cout << "داخل الدالة: " << x << endl;
}
// By Pointer - يغير الأصل
void incrementByPointer(int* ptr) {
(*ptr)++;
cout << "داخل الدالة: " << *ptr << endl;
}
// By Reference - الأسهل
void incrementByReference(int& ref) {
ref++;
cout << "داخل الدالة: " << ref << endl;
}
// تبديل قيمتين باستخدام مؤشرات
void swap(int* a, int* b) {
int temp = *a;
*a = *b;
*b = temp;
}
// إرجاع عدة قيم
void divideWithRemainder(int dividend, int divisor,
int* quotient, int* remainder) {
*quotient = dividend / divisor;
*remainder = dividend % divisor;
}
// إرجاع أكبر عنصر (مؤشر)
int* findMax(int* arr, int size) {
int* maxPtr = arr;
for (int i = 1; i < size; i++) {
if (arr[i] > *maxPtr) {
maxPtr = &arr[i];
}
}
return maxPtr;
}
int main() {
int num = 10;
cout << "=== By Value ===" << endl;
incrementByValue(num);
cout << "بعد الدالة: " << num << endl; // 10
cout << "\n=== By Pointer ===" << endl;
incrementByPointer(&num);
cout << "بعد الدالة: " << num << endl; // 11
cout << "\n=== By Reference ===" << endl;
incrementByReference(num);
cout << "بعد الدالة: " << num << endl; // 12
cout << "\n=== Swap ===" << endl;
int a = 5, b = 10;
cout << "قبل: a=" << a << ", b=" << b << endl;
swap(&a, &b);
cout << "بعد: a=" << a << ", b=" << b << endl;
cout << "\n=== إرجاع عدة قيم ===" << endl;
int q, r;
divideWithRemainder(17, 5, &q, &r);
cout << "17 ÷ 5 = " << q << " والباقي " << r << endl;
cout << "\n=== إرجاع مؤشر ===" << endl;
int arr[] = {3, 7, 2, 9, 5};
int* maxPtr = findMax(arr, 5);
cout << "أكبر عنصر: " << *maxPtr << endl;
return 0;
}اختبر فهمك