עבור לתוכן

Copy Elision

Featured Replies

פורסם

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

אני יודע משפת C, שכאשר מגדירים באופן מקומי משתנה שהוא מצביע כלשהו, או מבנה - אז כשמהדרים את התוכנית מתקבלת האזהרה:

[function returns address of local variable [enabled by default

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

ב-c++ העקרון דומה, אך הופתעתי לגלות כי בתוכנית הבאה:

[COLOR=#00008B][FONT=Consolas]class [/FONT][/COLOR][COLOR=#2B91AF][FONT=Consolas]MyClass[/FONT][/COLOR][COLOR=#393318][FONT=Consolas][COLOR=#000000]{[/COLOR][/FONT][/COLOR]
[COLOR=#00008B][FONT=Consolas]private[COLOR=#000000]:[/COLOR]
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] [COLOR=#2B91AF]int[/COLOR] color;
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] string name;
[/FONT][/COLOR][COLOR=#00008B][FONT=Consolas]public[COLOR=#000000]:[/COLOR]
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] [COLOR=#2B91AF]MyClass[/COLOR]([COLOR=#2B91AF]int[/COLOR] co, string n) :
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] name(n), color(co)
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] {
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] cout << [COLOR=#800000]"MyClass created"[/COLOR] << endl;
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] }
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] ~[COLOR=#2B91AF]MyClass[/COLOR]()
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] {
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] cout << [COLOR=#800000]"MyClass is deleted"[/COLOR] << endl;
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] }
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] string getName()
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] {
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] [COLOR=#00008B]return[/COLOR] [COLOR=#00008B]this[/COLOR]->name;
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] }
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas]};
[/FONT][/COLOR][FONT=Consolas][COLOR=#000000]
[/COLOR][/FONT]
[COLOR=#000000][FONT=Consolas][COLOR=#2B91AF]MyClass[/COLOR] func() [/FONT][/COLOR]
[FONT=Consolas][COLOR=#000000]
[/COLOR][/FONT][COLOR=#000000][FONT=Consolas]{
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] [COLOR=#2B91AF]MyClass[/COLOR] c([COLOR=#800000]0[/COLOR], [COLOR=#800000]"test"[/COLOR]);
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] [COLOR=#00008B]return[/COLOR] c;
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas]}
[/FONT][/COLOR][FONT=Consolas][COLOR=#000000]
[/COLOR][/FONT]

[FONT=Consolas][COLOR=#2b91af]void [/COLOR][COLOR=#000000]main[/COLOR][COLOR=#000000]()[/COLOR]
[/FONT][COLOR=#000000][FONT=Consolas]{
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] [COLOR=#2B91AF]MyClass[/COLOR] cls = func();
[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] cout << cls.getName() << endl;


[/FONT][/COLOR][COLOR=#000000][FONT=Consolas]}




Output:



[COLOR=#2B91AF]MyClass[/COLOR][COLOR=#000000] created
test [/COLOR]
[/FONT][/COLOR][COLOR=#2B91AF][FONT=Consolas]MyClass[/FONT][/COLOR][COLOR=#000000][FONT=Consolas] is deleted[/FONT][/COLOR]

כלומר, שה-d'tor נקרא בסיום ריצת ה-main ולא בסיום func

מישהו יודע להסביר מה קורה מאחורי הקלעים?

תודה

פורסם

בתכנית שלך הפונקציה func לא מחזירה מצביע - היא מחזירה אובייקט. כשאתה מחזיר אובייקט ב-++C אז האובייקט בעצם משוכפל (ע"י copy constructor) וככה אין שום הצבעה לזבל. מה שקורה הוא שבעצם נוצרים שני אובייקטים - אחד נוצר בתוך func ואחד נוצר מחוץ ל-func, שהוא עותק של האובייקט הראשון.

copy elision זו אופטימיזציה של הקומפיילר שמונעת את השכפול הזה. במקום ליצור את האובייקט בתוך הפונקציה ואז לשכפל אותו לתוך משתנה שנמצא מחוץ לפונקציה, הקומפיילר יוצר את האובייקט ישר בתוך המשתנה שמחוץ לפונקציה. ככה בעצם נוצר רק אובייקט אחד.

נ.ב. להבא, כשאתה כותב קוד בהודעה, תשתמש בטג קוד (כפתור עם ציור #).

פורסם
  • מחבר

אכן חיפשתי את האופציה לטג קוד, ערכתי, תודה.

קודם כל תודה, הארת את עיני לגבי האופן שהקומפיילר עושה זאת.

שאלה נוספת: בקוד שלי יש שכפול או שהאופטימיזציה גרמה לכך שהאובייקט נוצר פעם אחת בלבד?

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

הכתובת של האובייקט שנוצר בפונקציה מועברת ישירות למשתנה מחוץ לפונקציה שקולט אותו? כלומר הודות לאוטימזיציה הכתובת שלו מועברת כמו שהיא ולא נמחקת+משוכפלת למקום אחר?

תודה

פורסם

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

למעשה מה שיקרה שלא יווצר האובייקט c אלא הוא יהיה שם נוסף לאובייקט המוחזר שהאחריות לטיפול בו הוא על מי שקורא לפונקציה func.

הערה נוספת שלא קשורה לשאלה: היות והגדרת את color לפני name כדאי מאד לרשום את האתחול ב initialization list בסדר הזה אחרת יש פתח לבאגים מאד מעניינים.

ארכיון

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

דיונים חדשים