C++: المراجع
آخر تحديث: 2026-08-26
المؤشرات قوية، لكنها مرهقة نوعًا ما — تحتاج لكتابة
*pللتحويل، وتحتاج للحذر من المؤشرات الفارغة.C++ أدخلت المراجع — "أسماء مستعارة" للمتغيرات وهي أكثر أمانًا وبساطة من المؤشرات.
1. ما هي المرجع؟
(1) 1.1 المراجع في الحياة اليومية
| تشبيه من الحياة | المقابل البرمجي |
|---|---|
| لديك لقب "أحمد" — مناداتك بأي اسم تجدك | مرجع (اسم مستعار لمتغير) |
| الاسم على بطاقتك الشخصية مقابل اسمك اليومي | المرجع والمتغير الأصلي |
جوهر المرجع: المرجع هو اسم مستعار لمتغير — التعامل مع المرجع هو تعامل مع المتغير المُشار إليه.
(2) 1.2 لماذا نحتاج المراجع؟
باستخدام المؤشرات (مرهق):
▶ مثال 2: مثال برمجي (صعوبة ⭐)
#include <iostream>
void modifyValue(int* x) {
*x = 100; // Need dereference
}
int main() {
int a = 5;
modifyValue(&a); // Need to pass address
std::cout << a << std::endl; // 100
return 0;
}
الخرج:
(Program output)
باستخدام المراجع (بسيط):
#include <iostream>
void modifyValue(int& x) { // x Is a reference
x = 100; // Use directly,No dereference needed
}
int main() {
int a = 5;
modifyValue(a); // Looks like pass by value,Actually pass by reference
std::cout << a << std::endl; // 100
return 0;
}
2. تعريف المرجع وتهيئته
(1) 2.1 تعريف مرجع
الصياغة:
Type& Reference name = originalVariable;
مثال:
#include <iostream>
int main() {
int x = 5;
int& ref = x; // ref is alias of x
std::cout << "x = " << x << std::endl; // 5
std::cout << "ref = " << ref << std::endl; // 5
ref = 100; // modifying ref modifies x
std::cout << "After modification x = " << x << std::endl; // 100
return 0;
}
💡 نقطة مهمة: المراجع يجب تهيئتها — لا يمكنك التعريف أولًا ثم الإسناد لاحقًا.
(2) 2.2 المراجع مقابل المؤشرات
| المقارنة | المرجع | المؤشر |
|---|---|---|
| الصياغة | int& ref = x; |
int* p = &x; |
| يمكن أن يكون فارغًا؟ | ❌ لا (يجب التهيئة) | ✅ نعم (nullptr) |
| يحتاج تحويل؟ | ❌ لا (يُستخدم مباشرة) | ✅ نعم (*p) |
| يمكن إعادة الربط؟ | ❌ لا (بمجرد الربط، لا يمكن تغييره) | ✅ نعم (يمكن الإشارة لمتغير آخر) |
| التوصية | ⭐⭐⭐⭐⭐ (فضّل) | ⭐⭐⭐ (استخدم عند الحاجة) |
3. المراجع كمعلمات دالة
(1) 3.1 الاستخدام الأساسي
#include <iostream>
// Use reference parameters to "return" multiple values
void minMax(int arr, int length, int& min, int& max) {
min = arr[0];
max = arr[0];
for (int i = 1; i < length; i++) {
if (arr[i] < min) {
min = arr[i];
}
if (arr[i] > max) {
max = arr[i];
}
}
}
int main() {
int arr[5] = {3, 1, 4, 1, 5};
int min, max;
minMax(arr, 5, min, max); // min and max will be modified
std::cout << "Minimum: " << min << std::endl; // 1
std::cout << "Maximum: " << max << std::endl; // 5
return 0;
}
💡 نقطة مهمة: معلمات المرجع تتيح للدوال "إرجاع" قيم متعددة (بتعديل عدة معلمات مرجعية).
(2) 3.2 المراجع الثابتة (الأكثر استخدامًا)
إذا كنت لا تريد أن تعدّل الدالة المعلمة، لكنك لا تزال تريد تجنب تكلفة النسخ، استخدم مرجعًا ثابتًا.
#include <iostream>
#include <string>
void printName(const std::string& name) { // const reference: Cannot modify name
std::cout << "Name: " << name << std::endl;
// name = "Alice"; // ❌ Error: Cannot modify const reference
}
int main() {
std::string myName = "MOTO";
printName(myName); // No need to copy entire string, more efficient
return 0;
}
💡 القاعدة الذهبية: فضّل المراجع الثابتة لمعلمات الدوال — توازن بين الأمان والكفاءة.
4. أخطاء المراجع الشائعة
(1) 4.1 المراجع يجب تهيئتها
#include <iostream>
int main() {
int& ref; // ❌ Error: Reference requires initialization
return 0;
}
رسالة خطأ المترجم:
error: 'ref' declared as reference but not initialized
(2) 4.2 المراجع لا يمكن إعادة ربطها
#include <iostream>
int main() {
int x = 5;
int y = 10;
int& ref = x;
ref = y; // ❌ This is NOT rebinding! This changes x's value to y's value
std::cout << "x = " << x << std::endl; // 10
std::cout << "y = " << y << std::endl; // 10
return 0;
}
💡 نقطة مهمة: بمجرد ربط مرجع بمتغير، لا يمكن إعادة ربطه بمتغير آخر.
5. تطبيق: إرجاع قيم متعددة
▶ مثال 1: حساب القسمة والباقي (صعوبة ⭐⭐)
#include <iostream>
// Use reference parameters to "return" multiple values
void divide(int a, int b, int& quotient, int& remainder) {
quotient = a / b;
remainder = a % b;
}
int main() {
int a = 17, b = 5;
int q, r;
divide(a, b, q, r); // q and r will be modified
std::cout << a << " / " << b << " = " << q << " ... " << r << std::endl;
// Output:17 / 5 = 3 ... 2
return 0;
}
الخرج:
/ = ...
▶ مثال 3: المرجع كقيمة إرجاع دالة (صعوبة ⭐)
#include <iostream>
#include <string>
std::string name = "Zhang San"; // Global variable
// Return reference (not value)
std::string& getName() {
return name; // Returns a reference to name
}
int main() {
getName() = "Li Si"; // Modify global variable
std::cout << "name = " << name << std::endl;
return 0;
}
الخرج:
name =
❓ أسئلة شائعة
س: ما الفرق الحقيقي بين المراجع والمؤشرات؟ ج:> - المراجع هي أسماء مستعارة للمتغيرات؛ المؤشرات هي متغيرات تخزن عناوين > - المراجع يجب تهيئتها؛ المؤشرات يمكن أن تكون
nullptr> - المراجع لا يمكن إعادة ربطها؛ المؤشرات يمكن > - فضّل المراجع إلا إذا كنت تحتاج تمثيل "لا شيء" (فاستخدم مؤشرات) س: لماذا لا يمكن تمرير المصفوفات بالمرجع كمعلمات؟ ج: يمكن ذلك، لكن صياغة مراجع المصفوفات معقدة.نهج أبسط: استخدم
std::arrayأوstd::vector(ستُغطى لاحقًا).
س: هل تحسن المراجع كفاءة التشغيل؟ ج: لا. المراجع تُنفَّذ عادةً كمؤشرات تحت السطح، لذا كفاءة التشغيل متطابقة.
ما تحسنه هو كفاءة التطوير (الكود أنظف، أقل عرضة للأخطاء).
س: ما أهم شيء في المراجع؟ ج: افهم المفاهيم الأساسية أولًا، ثم عززها من خلال أمثلة التطبيق.
📖 ملخص
- المراجع هي أسماء مستعارة للمتغيرات؛ يجب تهيئتها عند التعريف
- المراجع مقابل المؤشرات: المراجع لا يمكن أن تكون فارغة، لا يمكن إعادة ربطها
- المراجع كمعلمات دالة: تعديل متغيرات خارجية، تجنب النسخ
- المراجع الثابتة يمكن ربطها بكائنات مؤقتة (تمديد عمرها)
- قيم إرجاع المراجع يمكن استخدامها كقيم يمنى
📝 تمارين
-
أساسي (صعوبة ⭐): اكتب دالة
void addTen(int& x)تضيف 10 إلى المتغير الممرر. اختبرها فيmain. -
متوسط (صعوبة ⭐⭐): اكتب دالة
void swap(int& a, int& b)تبدّل قيمتي متغيرين. اختبرها فيmain. -
تحدي (صعوبة ⭐⭐⭐): اكتب برنامجًا ينفذ "فرز ثلاثة أعداد":
-
اكتب دالة
void sortThree(int& a, int& b, int& c)تفرز ثلاثة أعداد تصاعديًا -
في
main، دع المستخدم يدخل ثلاثة أعداد، استدعِsortThree، ثم أخرج النتيجة المرتبة
6. 🚀 الخطوة التالية
الآن بعد أن تعلمت المراجع، لنتابع إلى تخصيص الذاكرة الديناميكي (الدرس 26) — إدارة الذاكرة يدويًا بـ new و delete، وفهم الفرق بين المكدس والكومة.