تحويل آمن إلى const char * - مشكلة العمر المؤقتة
سؤال
لدي قالب متابع محدد حتى أتمكن
/// cast using implicit conversions only
template <class To,class From>
inline To safe_cast( const From &from ) {return from;}
في كثير من الأحيان (على سبيل المثال ، عند تمرير الوسائط إلى sprintf ووظائف مماثلة) ، أود استخدام هذا القالب لإجراء تحويل من فئة سلسلة إلى سلسلة على غرار C. ومع ذلك ، فإنه يدل على أن هذا غير ممكن عندما يتم تمرير مؤقت ، لأن المؤقتة لن تعيش لفترة كافية.
النظر في المثال التالي:
class Object
{
public:
MyStringClass GetDebugName() const;
};
Object obj;
printf("%s",safe_cast<const char *>(obj.GetDebugName()));
يعيش المؤشر المؤقت من OBJ.GetDebugName () فقط أثناء SAFE_CAST والمؤشر غير صالح (يشير إلى بيانات السلسلة المؤقتة التي تم تدميرها بالفعل) عند داخل printf.
بصفتي حلًا ، أستخدم حاليًا لعبة Direct Direct بدون استدعاء قالب: const char *c = (const char *)(obj.GetDebugName()
, ، ولكن هذا له عيب في انخفاض السلامة من النوع ، حيث أن فريق الممثلين قوي بشكل غير ضروري (على سبيل المثال ، سينجح بصمت حتى لو كان OBJ.GetDebugName () سيعود ENT بدلاً من قيمة السلسلة). static_cast
قد يكون أفضل قليلاً ، ولكن حتى هذا قوي للغاية ، أود أن أحصل على خطأ في أي موقف يكون فيه المصبوب غير متأكد من أن يكون آمنًا.
1) إذا لم أكن مخطئًا ، فإن المعيار يقول إن وقت الحياة المؤقت هو بيان (ما لم يتم تمديده من خلال الالتزام بمرجع const ، وفي هذه الحالة يكون وقت حياة المرجع). عند النظر إلى مثال printf أعلاه ، لست متأكدًا تمامًا من ماهية "البيان" ، وإذا كان السلوك الذي رأيته مطابقًا أم لا. إذا كان البيان هو printf بأكمله ، فإن عمر const from & from أقصر - ما هو العمر الذي يجب أن أتوقعه من المؤقتة؟ هل يمكن لأحد أن يوضح؟
2) هل هناك طريقة أخرى لإجراء تحويل سيكون آمنًا ، لكن النتيجة ستعيش لفترة كافية لتكون مفيدة؟
يحرر:
من فضلك ، فكر في هذا النوع من الأسئلة العامة ، أنا أسعى للحصول على آلية كيف يمكن للتحويل مثل هذا القيام به فيما يتعلق مدى الحياة المؤقتة ، لست مهتمًا جدًا بحالة خاصة لأي فئة سلسلة معينة.
لتوضيح لماذا لا أرغب في استخدام .c_str أو وظيفة عضو مماثلة: أود أن يكون رمز التحويل هو نوع الملاحق ، لا أريد أن يعتمد الرمز على حقيقة أنني أعرف أن نوع السلسلة المحدد قد تم تنفيذه C_STR ، أنا تريد أن تعمل حتى إذا تم إرجاع فئة سلسلة مختلفة بواسطة ObjectDebugName ، أو حتى إذا كان ObjectDebugName سيعيد بالفعل const char * (الذي يستبعد إمكانية الاتصال.
المحلول
يمكنني إجراء مجموعة صريحة ولكنها آمنة
أود أن أسميها مصبوبًا ضمنيًا تم إنجازه بشكل صريح ، أو مجرد طاقم ضمني واضطراب.
1) إذا لم أكن مخطئًا ، فإن المعيار يقول إن وقت الحياة المؤقت هو بيان (ما لم يتم تمديده من خلال الالتزام بمرجع const ، وفي هذه الحالة يكون وقت حياة المرجع). عند النظر إلى مثال printf أعلاه ، لست متأكدًا تمامًا من ماهية "البيان" ، وإذا كان السلوك الذي رأيته مطابقًا أم لا. إذا كان البيان هو printf بأكمله ، فإن عمر const from & from أقصر - ما هو العمر الذي يجب أن أتوقعه من المؤقتة؟ هل يمكن لأحد أن يوضح؟
أنت محق ، يتم تدمير المؤقتة بعد، بعدما printf قد عاد. الرمز الذي قدمته يجب أن يعمل. إذا لم يحدث ذلك ، فهذا يعني أنك قد سددت بعض المعلومات المهمة.
نصائح أخرى
لا أعرف لماذا تستخدم فئة السلسلة الخاصة بك هنا. هل لدى الفصل وظيفة عضو للحصول على const char * منه؟
std :: string getDebugName () ؛
printf ("٪ s" ، getDebugName (). c_str ()) ؛
سيكون آمنًا لأن المؤقتة ستبقى صالحة خلال هذا البيان ، على سبيل المثال.
يمكنك استدعاء وظيفة التحويل مباشرة:
printf("%s", obj.GetDebugName().operator const char*());