עבור לתוכן

שאלה הבנה לגבי הקצאת זכרון בC++

Featured Replies

פורסם

אני לומד בבן גוריון וכמעט ולא נגעתי ב C++ (יודע C וJAVA).

אם הקצאה בSTACK היא בזמן קומפילציה וצריכה גודל מדויק של מבנה נתונים לא הבנתי מדוע קטע הקוד הבא תקין?

 
int main(){
ifstream in("file.txt");
string s ,line;
while(getline(in,line))
s+=line + "\n";

cout << s
}

אני ממש לא מבין איך S גדל וגדל והוא על הSTACK ללא NEW.

ב JAVA זה מאוד ברור כי כל STRING הוא על ה HEAP.

ד"א הקוד מהספר לחשוב ב C++ שהוא חינמי ברשת.

פורסם

string הוא קלאס שמכיל בתוכו מצביע, שמצביע למערך מוקצה דינמית ב-heap.

המערך הזה הוא מה שגדל, וה-string הפיזי (s, line) נשארים באותו גודל על ה-stack.

פורסם
  • מחבר

אז בעצם הוא אחראי למחוק את עצמו, כלומר מי עושה DELETE או FREE?

פורסם

ה destructor של string אחראי לנקות את הזכרון שהאובייקט הקצה. האובייקט עצמו מוקצה על ה stack אבל זה לא מונע ממנו (מהמימוש של המחלקה string) להקצות דינמית אובייקטים (כמו מערך תווים) על ה heap ולהחזיק מצביע אליהם.

פורסם
  • מחבר


{
string s("amir");
string* st = &s;
return st;
}

סליחה שאני מציק פשוט הדברים האלו חשובים לי.

מה דעתכם על קטע הקוד.

האם st יצביע על ערך חוקי מחוץ לבלוק.

פורסם

הוא יצביע על מה שנקרא ערך לא מוגדר.

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

אבל על פי ההגדרה, ההתנהגות בפניה למחרוזת מחוץ לקטע הזה היא לא מוגדרת.

פורסם

לכן לא מחזירים מפונקציה מצביע למשתנה שהוגדר בה (על ה stack). משתנה שמוגדר על ה stack בתוך פונקציה למשל צריך "לההרס" בתום הפונקציה. במקרה הזה ה destructor של s יקרא בסיום הפונקציה והאובייקט "משתחרר" אוטומטית. כמו ש bla7 אמר, יכול להיות שבמקרה משתנה עדיין יהיה תקין (במקרה הזה לא ה destructor של s יקרא ככה שהוא בכל מקרה הוא לא עאמור להיות שמיש) אבל אסור להסתמך על זה.

פורסם
  • מחבר

כן זה ברור, אבל יכולות לצוץ הרבה בעיות למשל:


{
string s("amir");
string* st = &s;
s=null;
return st;
}

קשה מאוד להבין מה קורה בכל מצב מוזר כזה, למי שרגיל לJAVA .

תודה רבה על התשובות

פורסם

כיוון ש-s אינו מצביע, הביטוי הזה לא יתקמפל:

s=null

אלא אם ל-string היה מוגדר אופרטור = שמקבל מצביע.

פורסם

הנה באג:



{
string *ps
{
string s;
s = "abc";
ps = &s;
}

*ps = "def"; // this is a bug!!!
}

צורה דומה של הבאג שקצת יותר נפוצה אצל אנשים שלא יודעים C++ כמו שצריך:


string* get_name()
{
string name = "Zelig";
return &name; // BUG! (dangling reference)
}

פורסם

כן זה ברור, אבל יכולות לצוץ הרבה בעיות למשל:


{
string s("amir");
string* st = &s;
s=null;
return st;
}

קשה מאוד להבין מה קורה בכל מצב מוזר כזה, למי שרגיל לJAVA .

תודה רבה על התשובות

אגב, null (המילה השמורה) לא קיימת ב c++ . קיים בספריות של c מאקרו NULL ששווה אפס אבל אין מילה שמורה כזו בשפה. אולי אתה מערבב קצת עם java.

פורסם
  • מחבר

כן הכוונה למקרו

ד"א הוא לא


(void *) 0;

?

פורסם

נדמה לי שב c הוא בדר"כ (void*)0 אבל ב c++ זה בעייתי יותר (בגלל שהיא נוקשה יותר מבחינת המרת טיפוסים מאשר c ) ושם עדיף להשתמש ב 0.

פורסם

תשתמש ב-NULL.

קבצי H שבאים עם הקומפיילר אמורים להגדיר את NULL נכון בהתאם לאיך שאתה מקמפל כרגע, ולכן NULL עובד ב-99.99% מהמקרים.

ב-C++ אתה יכול להשתמש ב-0 (למעשה גם ב-C) אבל אני ממליץ תמיד להשתמש ב-NULL על מנת להפריד עבודה עם מצביעים לבין מספרים.

ארכיון

דיון זה הועבר לארכיון ולא ניתן להוסיף בו תגובות חדשות.

דיונים חדשים