سؤال

لقد واجهت سلوكًا غريبًا مع فئة C++ بسيطة.

كلاس أ.ح

class A
{
public:
  A();
  ~A();
  static const std::string CONST_STR;
};

classA.cpp

#include "classA.h"
#include <cassert>

const std::string A::CONST_STR("some text");

A::A()
{
  assert(!CONST_STR.empty()); //OK
}

A::~A()
{
  assert(!CONST_STR.empty()); //fails
}

main.cpp

#include <memory>  
#include <classA.h>  

std::auto_ptr<A> g_aStuff; 

int main() 
{ 
  //do something ... 
  g_aStuff = std::auto_ptr<A>(new A()); 
  //do something ... 
  return 0; 
}

كنت أتوقع حدوث انتهاكات للوصول أو أي شيء مشابه، لكنني لم أتوقع أبدًا أن يتغير محتوى سلسلة الثوابت الثابتة.هل لدى أي شخص هنا تفسير جيد لما يحدث في هذا الرمز؟

شكرا ، نوربرت

هل كانت مفيدة؟

المحلول

<اقتباس فقرة>   

وأتوقع انتهاكات الوصول أو   أي شيء مماثل، ولكن أتوقع أبدا   أن محتوى CONST ثابت   سلسلة يمكن أن يتغير.

والسلوك غير معرفة: فهو غير معروف. إذا كان قد تم تدمير CONST_STR، فأنت غير مضمونة استثناء الأجهزة إذا كنت الوصول إليه. قد تحطم الطائرة، ولكن بعد ذلك مرة أخرى عنوانه قد ينتهي تحتوي على البيانات التي تبدو وكأنها سلسلة فارغة: المدمر قوتها مسح مؤشرات أو أيا كان

في هذه الحالة، ويقول لك أنه يتم تخزين مثيل أيضا في مؤشر الذكية العالمية، الذي تم تعيينه في main (). لذلك تم بناؤها CONST_STR عندما يتم الوصول إليه في منشئ، ولكن من المحتمل جدا دمرت قبل أن يتم تدمير مؤشر الذكية. كنا بحاجة إلى برنامج كامل لالجزم.

[تحرير: كنت قد فعلت ذلك. حيث يتم تعريف CONST_STR وg_aStuff في وحدات تجميع مختلفة، لم يتم تعريف النظام النسبي بنائها وفق المعايير. انا التخمين أن CONST_STR تدمر أولا.]

نصائح أخرى

يحرر: على ما يبدو في عداد المفقودين A:: كان خطأ مطبعي في المشاركة الأصلية للكود.

الجواب الأصلي:

هل تقصد أن يكون لديك


    const std::string أ::CONST_STR("some text");

بحيث يكون CONST_STR جزءًا من الفصل A?

وإلا فإنك تعلن ذلك بشكل منفصل و لا تهيئة العضو الثابت لـ A.

وأنت خلق 2 المتغيرات ثابتة في وحدتين تجميع مختلفة. ليس هناك طريقة لمعرفة في أي ترتيب يتم تهيئة. ولكن تالفة بهم تسمى دائما بترتيب عكسي.

في حالتك يبدو أن السيناريو القادم وقعت:

g_aStuff constructor 
CONST_STR constructor

main funciton initializes g_aStuff

CONST_str destructor 
g_aStuff descrutor  

وعند هذه النقطة نتيجة CONST_STR.empty () هو غير معروف. والتي قد تؤدي إلى تأكيد.

و

const std::string CONST_STR("some text");
المحددة في classA.cpp ليس عضوا في A. وهذا تعريف تبدو:

const std::string A::CONST_STR("some text");

وهذا المعيار لا يحدد ترتيب تهيئة كائنات العالمية / ثابت في وحدات الترجمة المختلفة. فإنه، مع ذلك، ضمان أن كل هذا الكائن سيتم تهيئة قبل تنفيذ أي وظيفة من تلك الوحدة الترجمة.

في قضيتك، يحدث أن CONST_STR تتم تهيئة بعد g_aStuff، وبما أن ترتيب التدمير هو عكس من أجل البناء، ويحصل على تدميره قبل ذلك. وبالتالي، الوصول إلى CONST_STR من المدمر A لاستدعاء سلوك غير معرف - قد تحصل على انتهاك وصول أو أنك قد لا

وهو، ومع ذلك، تهيئة قبل منشئ CONST_STR في تنفيذ A لأنهم في وحدة الترجمة نفسها.

وقد يحدث إذا كان هناك مثيل العالمي من A (أو أحد أفراد الطبقة ثابت من نوع A). منذ لم يتم تعريف ترتيب تهيئة غلوبالس واحصائيات (وحدات عبر الترجمة)، فإنه يمكن أن يكون.

وعند النظر إلى التعليمات البرمجية الخاصة بك كامل، كنت تعتمد على ترتيب التدمير عبر وحدات تجميع (classA.cpp وMAIN.CPP). إذا قمت بإنشاء g_aStuff كما محلية في main، يؤكد الخاصة بك ينبغي أن تمر.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top