Menu
Coddy logo textTech

זיכרון דינמי (new/delete)

חלק מהיחידה תכנות מונחה עצמים במסלול ה-C++ של Coddy. שיעור 14 מתוך 104.

עכשיו, אחרי שהבנת מצביעים והפניות, בוא נשתמש בהם כדי לבצע הקצאת זיכרון דינמית. האופרטורים new ו־delete מאפשרים לך ליצור ולהשמיד אובייקטים בערימה בזמן ריצה.

השתמשו ב-new כדי להקצות זיכרון ולקבל מצביע אליו:

int* num = new int;        // הקצה מספר שלם יחיד
*num = 42;                 // הצב ערך באמצעות מצביע

Player* player = new Player("Hero");  // הקצה אובייקט

לכל new חייב להיות delete תואם כדי לשחרר את הזיכרון:

delete num;      // משחרר אובייקט יחיד
delete player;   // קורא ל-destructor, ואז משחרר את הזיכרון

עבור מערכים, השתמשו ב־new[] וב־delete[]:

int* scores = new int[5];    // הקצה מערך של 5 מספרים שלמים
scores[0] = 100;

delete[] scores;             // שחרר את המערך - שים לב לסוגריים המרובעים!

טעויות נפוצות שיש להימנע מהן:

// דליפת זיכרון - שכחנו לבצע delete
int* ptr = new int(10);
ptr = new int(20);    // אבדה הגישה להקצאת הזיכרון הראשונה!

// מצביע תלוי - שימוש לאחר delete
delete ptr;
*ptr = 5;             // התנהגות לא מוגדרת!

// שימוש ב-delete לא תואם
int* arr = new int[10];
delete arr;           // שגוי! צריך להשתמש ב-delete[]

לאחר המחיקה, הגדירו את המצביעים ל־nullptr כדי להימנע משימוש חוזר בשוגג. ניהול זיכרון ידני מועד לשגיאות, ולכן C++ מודרנית מעדיפה מצביעים חכמים, שבהם נעסוק בהמשך.

challenge icon

אתגר

קל

בואו נבנה מערכת פשוטה לאחסון הודעות, המדגימה הקצאת זיכרון דינמית באמצעות new ו־delete.

תיצרו שני קבצים כדי לארגן את הקוד:

  • MessageBox.h: הגדירו מחלקה בשם MessageBox שמנהלת מערך הודעות באופן דינמי. המחלקה צריכה לכלול:
    • מצביע פרטי למערך מחרוזות שהוקצה באופן דינמי
    • מספר שלם פרטי שעוקב אחר מספר ההודעות הנוכחי
    • מספר שלם פרטי ששומר את הקיבולת המרבית
    • בנאי שמקבל קיבולת ומקצה את המערך באמצעות new[]
    • הורס שמשחרר כראוי את הזיכרון באמצעות delete[] ומדפיס "MessageBox destroyed"
    • מתודה בשם addMessage(string msg) שמוסיפה הודעה אם יש מקום, ומחזירה true במקרה של הצלחה או false אם המערך מלא
    • מתודה בשם printAll() שמדפיסה כל הודעה שמורה בשורה נפרדת
  • main.cpp: קראו מהקלט ערך של קיבולת ומספר הודעות. לאחר מכן קראו את מספר מחרוזות ההודעה הזה. צרו אובייקט MessageBox בערימה באמצעות new, הוסיפו אליו את כל ההודעות, קראו למתודה printAll(), ואז מחקו כראוי את האובייקט MessageBox כדי לשחרר את הזיכרון.

פורמט הקלט יהיה:

  • שורה ראשונה: הקיבולת (מספר שלם)
  • שורה שנייה: מספר ההודעות להוספה (מספר שלם)
  • השורות הבאות: הודעה אחת בכל שורה

זכרו: לכל new נדרש delete תואם, ולכל new[] נדרש delete[] תואם. לאחר מחיקה, מומלץ להציב nullptr במצביעים.

כללו את קובץ הכותרת שלכם ב־main.cpp באמצעות #include "MessageBox.h".

נסו בעצמכם

#include <iostream>
#include <string>
#include "MessageBox.h"
using namespace std;

int main() {
    int capacity;
    int numMessages;
    
    // קרא את הקיבולת ואת מספר ההודעות
    cin >> capacity;
    cin >> numMessages;
    cin.ignore(); // נקה את תו השורה החדשה שאחרי המספר
    
    // TODO: צור MessageBox בערימה באמצעות new
    
    // TODO: קרא והוסף את כל ההודעות ל-MessageBox
    for (int i = 0; i < numMessages; i++) {
        string message;
        getline(cin, message);
        // הוסף הודעה ל-MessageBox
    }
    
    // TODO: קרא ל-printAll() כדי להציג את כל ההודעות
    
    // TODO: מחק את ה-MessageBox כדי לפנות זיכרון
    // זכור להגדיר את המצביע ל-nullptr לאחר המחיקה
    
    return 0;
}
quiz iconבחנו את עצמכם

השיעור הזה כולל חידון קצר. התחילו את השיעור כדי לענות עליו ולעקוב אחרי ההתקדמות.

כל השיעורים ביחידה תכנות מונחה עצמים

תרגלו בעצמכם: קומפיילר C++ אונליין