ניהול חיי המשאבים הוא נושא בסיסי שיש לשלוט בו בC++
.
זאת מכיוון שC++
היא שפה בלתי מנוהלת.
ל-C++
יש Runtime
שמבצע דברים מאוד בסיסיים.
אך אם ברצוננו למחוק זיכרון, לשחרר נעילת קובץ, לשחרר תהליכון רץ - עלינו לעשות זאת לבד.
בתרגום חופשי ניתן לומר “השגת משאב הוא ביצירתו”.
RAII
משתמש בטכניקה קשירת המשאב לחיי אובייקט.
כפי שידוע חיי אובייקט מוגדר ע”פ ה-Scope
שלו.Scope
מוגדר בעזרת סוגריים מסולסלות { ... }
.
1 | struct A { }; |
כדי להדגים את היכולת ניצור מחלקה משלנו לניהול חיי זיכרון.
זיכרון מוקצה ע”י המילה השמורה new
:
1 | int* var = new int(5); |
וכדי למחוק אותו נצטרך למחוק בצורה מפורשת:
1 | delete var; |
זה יוצר מגוון בעיות:
כדי להקל על יצירת ומחיקה ושימוש לא מפורש ביצירת הזיכרון נבצע נכמס את הפעולה הזו במחלקה.
הטכניקה משתמשת בבנאי כאתחול המשאב - אם יצירת המשאב נכשלת נזרקת שגיאה.
1 | struct EncapsulatePtr |
כאשר נשתמש במשאב נוכל ליצור את המופע של המחלקה:
1 | int main() |
כדי למחוק את המשאב נשתמש ב-dtor
.
יש להימנע מזריקת שגיאות בעת מחיקת המשאב כדי לא להתעסק בזה בצורה מפורשת.
מחיקת משאבים אמורה להיות נקייה משגיאות ו”חלקה”.
1 | struct EncapsulatePtr |
כעת השימוש בו הוא אוטומטי, לא צריך אפילו לחשוב על מחיקת המשאב:
1 | int main() |
בספריית C++
הסטנדרטית קיימים דוגמאות לשימוש בקונספט:
הדוגמא הקלאסית היא מחרוזת.
מאחורי הקלעים קיימת מחרוזת מוקצת מראש למחרוזות קטנות - אך אם אנחנו מקצים מחרוזת ענקית על המחלקה להקצות זיכרון חדש.
1 | int main() |
ווקטור הוא לא השם הכי מוצלח למחלקה הזו - שם מוצלח יהיה list
או dynamic list
.
std::list
.1 | int main() |
והדוגמא הכי קלאסית תהיה נעילות אוטומטיות:
1 | std::mutex mutex; |
נעילה תהיה ע”י קריאה למתודות lock
ו-unlock
.
מה לא לעשות:
1 | void Dont() |
מה כן לעשות:
1 | void Do() |
אי אפשר לדבר על RAII
מבלי להזכיר את ה-Smart pointers
.
במקום לנהל את המצביע לבד או לכתוב מחלקות בשביל זה יש לנו כמה מחלקות שעוזרות לנו:
std::unique_ptr
- מצביע שיש אותו רק פעם אחת. std::shared_ptr
- מצביע השומר את כמות הייחסות למצביע.זהו סוג של “מנגנון אוטומטי” לאיסוף זיכרון הנותן לנו שליטה על הבעלות על המצביע.
מהסיבה הזו יש קונבנציות המורות על שימוש במצביע נקי רק בשביל “להתייחס” לזיכרון ולא כבעלות לזיכרון.
1 | { |
טכניקת RAII
פופולרית בשפה ויש לשלוט בה כדי לנהל משאבים בצורה חכמה.
השימוש במחלקה עוזרת בכך שניתן לממש עיצובים שונים למחלקות ולבנות היררכיות שייטפלו בכל המשאבים.
גם בירושה או הכלה.
זיכרון לא מנוהל זה זיכרון אבוד :)
תודה על הקריאה!