في الدروس السابقة تعلمت المصفوفات العادية (Static Arrays) مثل:
int arr[10];
هذه المصفوفات مفيدة…
لكن عندها أكبر مشكلة في تاريخ البرمجة:
❌ عدد عناصرها يجب أن يكون ثابت وقت الترجمة (Compile-Time)
❌ لا تستطيع تغيير حجمها أثناء التشغيل
❌ تستخدم الـ Stack — مساحة صغيرة جدًا مقارنة بالـ Heap
ولأن C++ لغة منخفضة المستوى…
فهي تعطيك قوة كاملة للتحكم بالذاكرة باستخدام الذاكرة الديناميكية (Dynamic Memory).
وهذا بالضبط موضوع هذا الدرس 🔥
🎯 ما هي المصفوفات الديناميكية؟
هي مصفوفات يتم إنشاؤها أثناء تشغيل البرنامج (Runtime)
وليس أثناء الترجمة.
تُخزّن في منطقة Heap بدلاً من Stack.
بمعنى آخر:
أنت الذي تحدد حجمها وقت التشغيل، سواء من المستخدم، أو من بيانات خارجية.
🧩 الصيغة الأساسية للذاكرة الديناميكية
🔸 إنشاء متغير بشكل ديناميكي
int* p = new int;
🔸 إنشاء مصفوفة ديناميكية
int* arr = new int[size];
هذا السطر يحجز size عنصر في الذاكرة Heap.
⚡ لماذا نستخدم Dynamic Arrays؟
- ✔ حجمها يُحدد أثناء تشغيل البرنامج
- ✔ يمكن تغيير حجمها (بعمليات خاصة)
- ✔ مناسبة للبيانات الكبيرة
- ✔ ضرورية للـ Data Structures المتقدمة مثل:
- Linked List
- Dynamic Vector
- Binary Trees
- Graphs
- ✔ لأن المكتبات القياسية STL كلها مبنية على الذاكرة الديناميكية
🚀 أولًا: استخدام new لإنشاء مصفوفة ديناميكية
📘 مثال أساسي:
#include <iostream>
using namespace std;
int main() {
int n;
cout << "أدخل حجم المصفوفة: ";
cin >> n;
int* arr = new int[n]; // إنشاء مصفوفة ديناميكية
for(int i = 0; i < n; i++) {
cin >> arr[i];
}
cout << "العناصر المدخلة: ";
for(int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
delete[] arr; // تحرير الذاكرة
}
🔍 شرح مهم جدًا:
🔸 new int[n]
- ينشئ مصفوفة ديناميكية حجمها n
- يخزنها في Heap
- يعيد مؤشر لأول عنصر
- المتغير
arrهو pointer وليس array حقيقية
🔸 delete[] arr
يحذف المصفوفة الديناميكية كاملة من الذاكرة.
💥 إذا نسيت delete → صار عندك Memory leak
يعني ذاكرة محجوزة لكن غير مستخدمة.
🧠 ثانيًا: الفرق بين Stack و Heap
| الخاصية | Stack | Heap |
|---|---|---|
| مكان المصفوفة | داخل إطار الدالة | خارج الدالة |
| الحجم | صغير | كبير جدًا |
| سرعة الوصول | سريع | أبطأ |
| التحكم | تلقائي | يدوي باستخدام new/delete |
| غض الطرف يؤدي | خطأ compile/runtime | memory leak |
🧱 ثالثًا: مثال عملي كبير — بناء مصفوفة ديناميكية وتعديلها
#include <iostream>
using namespace std;
int main() {
int n;
cout << "أدخل حجم المصفوفة: ";
cin >> n;
int* arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = i * 2;
}
cout << "محتوى المصفوفة: ";
for (int i = 0; i < n; i++) {
cout << arr[i] << " ";
}
delete[] arr;
}
🎯 رابعًا: تعديل حجم المصفوفة الديناميكية (Dynamic Resize)
C++ لا تملك دالة جاهزة مثل realloc() في C،
لكن يمكنك زيادة حجم المصفوفة يدويًا:
📘 الطريقة:
- إنشاء مصفوفة جديدة بالحجم الجديد
- نقل البيانات إليها
- حذف القديمة
📦 مثال: زيادة حجم المصفوفة من n إلى n+5
int* resizeArray(int* arr, int oldSize, int newSize) {
int* newArr = new int[newSize];
for (int i = 0; i < oldSize; i++) {
newArr[i] = arr[i];
}
delete[] arr;
return newArr;
}
⚡ خامسًا: المصفوفات الديناميكية متعددة الأبعاد
🎯 مصفوفة 2D ديناميكية:
int** arr = new int*[rows];
for(int i = 0; i < rows; i++) {
arr[i] = new int[cols];
}
📘 وطبعًا لا تنسى حذفها:
for(int i = 0; i < rows; i++) {
delete[] arr[i];
}
delete[] arr;
🧩 سادسًا: new vs malloc (مهم جدًا)
| المقارنة | new | malloc |
|---|---|---|
| اللغة | C++ | C |
| تعيد النوع الصحيح؟ | نعم | لا، void* |
| تستدعي constructor؟ | ✔ | ❌ |
| تستخدم مع delete | ✔ | ❌ |
| سهلة الاستخدام | ✔ | ❌ |
🔥 سابعًا: أخطاء الذاكرة الشائعة — والحلول
1️⃣ نسيان delete
❌ خطير جدًا → Memory Leak
✔ الحل: استخدم دائمًا delete بعد new
2️⃣ استخدام delete بدون new
int x;
delete &x; // كارثة
📛 هذا يدمر الذاكرة.
3️⃣ استخدام delete بدلاً من delete[]
❌ خطأ شائع جدًا
int* arr = new int[10];
delete arr; // خطأ
✔ يجب:
delete[] arr;
🧠 ثامنًا: dynamic arrays vs vector
| الميزة | dynamic array | vector |
|---|---|---|
| سرعة | أسرع قليلًا | قريب جدًا |
| سهولة الاستخدام | صعب | سهل جدًا |
| تغيير الحجم | يدوي | تلقائي |
| أمان | أقل | أعلى |
| حذف الذاكرة | يدوي | تلقائي |
💬 نصيحتي كمبرمج محترف:
استخدمvectorدائمًا…
واستخدمnewفقط لو كنت تبني نظام كبير جدًا أو embedded أو memory-oriented.
🧪 تاسعًا: مثال مشروع صغير كامل — حساب القيم باستخدام المصفوفات الديناميكية
#include <iostream>
using namespace std;
int main() {
int n;
cout << "أدخل عدد الطلاب: ";
cin >> n;
double* grades = new double[n];
for (int i = 0; i < n; i++) {
cout << "أدخل علامة الطالب " << i+1 << ": ";
cin >> grades[i];
}
double sum = 0;
for (int i = 0; i < n; i++) {
sum += grades[i];
}
cout << "المعدل: " << (sum / n) << endl;
delete[] grades;
}
🌍 روابط خارجية موثوقة
🔗 cppreference – new/delete
https://en.cppreference.com/w/cpp/language/new
🎯 الخلاصة النهائية
المصفوفات الديناميكية هي:
✔ أساس مفهوم إدارة الذاكرة
✔ تستخدم new و delete للتحكم الكامل
✔ تخزّن على Heap
✔ يمكن تغيير حجمها
✔ هي الأساس لكل تراكيب البيانات الكبيرة (Vector, Map, Graph, Trees)
✔ تعطيك قوة ومرونة لا تملكها لغات كثيرة
إذا فهمت هذا الدرس صح…
فأنت الآن قادر تتعامل مع الذاكرة في C++ مثل المحترفين.
اكتشاف المزيد من كود التطور
اشترك للحصول على أحدث التدوينات المرسلة إلى بريدك الإلكتروني.


