Whatsup - לינוקס, תוכנה חופשית וקוד פתוח בעברית

תיכנות בלינוקס - מערך דינמי של אובייקטים עם קונסטרוקטור

Anonymous - 04/03/2018 - 12:37
נושא ההודעה: מערך דינמי של אובייקטים עם קונסטרוקטור
1) שאלה: ביצירת מערך דינמי של מספר אובייקטים עם "קונסטרוקטור", מצד אחד אם לא מאתחלים את האובייקטים מתקבלת שגיאה, שהרי יש "קונסטרוקטור" באובייקטים האמור לקבל ערך בשעת יצירת האובייקט, וכאן הוא לא מתקבל. מצד שני אם כן מאתחלים עם ערך מתקבלת שגיאה שהדבר אסור על פי תקן ISO. כיצד פותרים את הבעיה?.

לדוגמה נניח ש-intc היא מחלקה
קוד:
intc_ptr = new intc[100];

יביא לשגיאה כי אין ערך לקונסטרוקטור
ומצד שני
קוד:
intc_ptr = new intc[100](45)

יביא לשגיאה הבאה:
קוד:
ISO C++ forbids initialization in array

Anonymous - 04/03/2018 - 13:05
נושא ההודעה:
אין כזה דבר מערך דינאמי של אובייקטים. או שזה מערך (כלומר לא דינאמי) או שזה מחלקה שמממשת מערך דינאמי ואז אתה מאתחל את זה כמו מחלקה.
Anonymous - 04/03/2018 - 13:05
נושא ההודעה:
נראה לי סוגריים מסולסלים, ועם c++11
Anonymous - 04/03/2018 - 17:47
נושא ההודעה:
Anonymous :
אין כזה דבר מערך דינאמי של אובייקטים. או שזה מערך (כלומר לא דינאמי) או שזה מחלקה שמממשת מערך דינאמי ואז אתה מאתחל את זה כמו מחלקה.


std::array Razz
Anonymous - 04/03/2018 - 18:09
נושא ההודעה: Re: מערך דינמי של אובייקטים עם קונסטרוקטור
C++ist :
1) שאלה: ביצירת מערך דינמי של מספר אובייקטים עם "קונסטרוקטור", מצד אחד אם לא מאתחלים את האובייקטים מתקבלת שגיאה, שהרי יש "קונסטרוקטור" באובייקטים האמור לקבל ערך בשעת יצירת האובייקט, וכאן הוא לא מתקבל. מצד שני אם כן מאתחלים עם ערך מתקבלת שגיאה שהדבר אסור על פי תקן ISO. כיצד פותרים את הבעיה?.

לדוגמה נניח ש-intc היא מחלקה
קוד:
intc_ptr = new intc[100];

יביא לשגיאה כי אין ערך לקונסטרוקטור
ומצד שני
קוד:
intc_ptr = new intc[100](45)

יביא לשגיאה הבאה:
קוד:
ISO C++ forbids initialization in array


שנות ה 90 התקשרו ומבקשות את הפרקטיקות שלהן בחזרה. std::vector או std::array עדיף ברוב המקרים כשיש לך משהוא ידוע מראש.

אבל אתה ככל הנראה מחפש משהוא כמו :

std::unique_ptr<int[]> p (new int[100]());
borsood - 05/03/2018 - 08:03
נושא ההודעה:
std::array ו std::vector עדיפות תמיד.
לא משתמשים במערכים של C בקוד חדש.

ולכן:

קוד:
auto arr = std::array<intc, 10>{1,2,3,4,5,42,42,42,42,42};


או
קוד:
auto vec1 = std::vector<intc>{1,2,3,4,5,42,42,42,42,42};

auto vec2 = std::vector<intc>(100,42);

Anonymous - 05/03/2018 - 09:26
נושא ההודעה:
borsood :
std::array ו std::vector עדיפות תמיד.
לא משתמשים במערכים של C בקוד חדש.


נכון שבדרך כלל זו הדרך העדיפה, אבל עדיין יש מקרים, כמו כתיבה של קוד low-level, בהם הדבר הנכון הוא הקצאה ישירה של זיכרון.

לגבי השאלה המקורית:

כאשר מקצים מערך של אלמנטים מסוג של class מסוים בלי לספק דרך לאתחול האלמנטים, כל אלמנט במערך מאותחל בעזרת ה-default ctor. אם לא קיים default ctor, ההתנהגות לא תמיד מוגדרת. ככלל צריך תמיד לספק default ctor כדי שההתנהגות תהיה תמיד צפויה וידועה.

באיזו גרסה של C++ אתה משתמש? אצלי, ב-2011, הדוגמה הראשונה שלך מתקמפלת בלי שגיאה (בהנחה שהגדרת לפני כן את intc_ptr).
Anonymous - 05/03/2018 - 11:36
נושא ההודעה:
עמית :
borsood :
std::array ו std::vector עדיפות תמיד.
לא משתמשים במערכים של C בקוד חדש.


נכון שבדרך כלל זו הדרך העדיפה, אבל עדיין יש מקרים, כמו כתיבה של קוד low-level, בהם הדבר הנכון הוא הקצאה ישירה של זיכרון.


std::vector::resize , אם אתה כותב "low level" ועושה את זה ב C++ אתה יורה בהעתקים של הרגל שלך.
Anonymous - 05/03/2018 - 12:15
נושא ההודעה:
ציטוט:
אם אתה כותב "low level" ועושה את זה ב C++ אתה יורה בהעתקים של הרגל שלך.


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

עדיין עשויים להיות מקרים מסויימים, למשל שתרצה לכתוב בעצמך container class שלא קיים ב-STL, או שיהיו לך אילוצים של חומרה מסוימת, בהם תרצה לעשות, למשל, הקצאות זיכרון בעצמך.
Anonymous - 05/03/2018 - 18:47
נושא ההודעה:
עמית :
ציטוט:
אם אתה כותב "low level" ועושה את זה ב C++ אתה יורה בהעתקים של הרגל שלך.


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

עדיין עשויים להיות מקרים מסויימים, למשל שתרצה לכתוב בעצמך container class שלא קיים ב-STL, או שיהיו לך אילוצים של חומרה מסוימת, בהם תרצה לעשות, למשל, הקצאות זיכרון בעצמך.


בוא נתחיל מזה שאף אחד לא משתמש ב STL בדר"כ , אנשים משתמשים בספרייה הסטאנדרטית.
חלק גדול מהקונטיינרים של הספרייה הסטאנדרטית תומכים ב memory allocator type אם אתה באמת רוצה להשתמש בזה.

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

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

זו בדיוק הסיבה בה אמרתי תייצר std::vector ובצע resize לדוגמה , ואז אתה מעביר instance.data() או &instance[0] לפונקציה שמקבלת מצביע לטיפוס בסיס.
קוד:

extern void f1(int8_t * ptr,size_t count_of_elements);

void foo()}
std::vector <int8_t> v;
v.resize(1000);
f1(v.data(),v.size());
{

Anonymous - 06/03/2018 - 11:49
נושא ההודעה:
אני מסכים איתך במישור העקרוני, הויכוח בינינו הוא לא על העקרונות. כל מה שרציתי לומר הוא שבמקרה שהמבנים הקיימים בשפה (ובספרייה הסטנדרטית - אתה צודק, לזה התכוונתי) לא עונים על צרכים מאד מסוימים (ואני מסכים שזה נדיר) יש אפשרות לעבוד גם ב-level יותר נמוך.

מעבר לזה, זה דברים שלעניות דעתי מתכנתים צריכים לדעת, גם אם הם ישתמשו רק בספרייה הסטנדרטית. זה גם אחד הדברים היפים (יש כאלה שיגידו בדיוק להיפך) ב-C++, שלצד ההפשטה והספרייה העשירה יש אפשרות גם לעבוד ב-low level.
כל הזמנים הם GMT + 2 שעות