كيفية القيام بإزالة التداخل الثابت إذا كان للمدمر آثار جانبية وتم الوصول إلى الكائن من مدمرة كائن ثابت آخر؟

StackOverflow https://stackoverflow.com/questions/3143180

سؤال

هناك نمط بسيط ومعروف لتجنب إخفاق التهيئة الثابتة ، الموصوفة في القسم 10.13 من الأسئلة الشائعة C ++.

في هذا النمط القياسي ، هناك مفاضلة تم إجراؤها من حيث أنه لا يتم تدمير الكائن المبني أبدًا (وهذا ليس مشكلة إذا لم يكن للمدمر آثار جانبية مهمة) أو لا يمكن الوصول إلى الكائن الثابت بأمان من تدمير كائن ثابت آخر (نرى القسم 10.14 من الأسئلة الشائعة C ++).

لذا فإن سؤالي هو: كيف تتجنب إخفاق إزالة التنازل الثابت إذا كان للتدمير المكون من كائن ثابت آثار جانبية مهمة يجب أن تحدث في النهاية و يجب الوصول إلى الكائن الثابت من قبل تدمير كائن ثابت آخر؟


(ملاحظة: يذكر الأسئلة الشائعة بين هذا السؤال في الأسئلة الشائعة 16.17 من الأسئلة الشائعة C ++: أسئلة يتم طرحها بشكل متكرر بقلم M. Cline و G. Lomow. ليس لدي إمكانية الوصول إلى هذا الكتاب ، ولهذا السبب أطرح هذا السؤال بدلاً من ذلك.)

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

المحلول

يتم ضمان تدمير الكائنات الثابتة للوظيفة مثل الكائنات العالمية (على افتراض أنها تم إنشاؤها).

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

الرابط التالي يدور حول Singeltons ولكنه يصف موقفًا مشابهًا وحله:
إيجاد مشاكل ترتيب التهيئة الثابت C ++

استقراء إلى الحالة العامة للكرات الكسول المهيئة كما هو موضح في الأسئلة الشائعة ، يمكننا حل مشكلة مثل هذه:

namespace B
{
    class B { ... };

    B& getInstance_Bglob;
    {
        static B instance_Bglob;
        return instance_Bglob;;
    }

    B::~B()
    {
         A::getInstance_abc().doSomthing();
         // The object abc is accessed from the destructor.
         // Potential problem.
         // You must guarantee that abc is destroyed after this object.
         // To gurantee this you must make sure it is constructed first.
         // To do this just access the object from the constructor.
    }

    B::B()
    {
        A::getInstance_abc();
        // abc is now fully constructed.
        // This means it was constructed before this object.
        // This means it will be destroyed after this object.
        // This means it is safe to use from the destructor.
    }
}
namespace A
{
    class A { ... };

    A& getInstance_abc()
    {
        static A instance_abc;
        return instance_abc;
    }
}

نصائح أخرى

طالما أن المدمرة الثابتة للكائن الآخر يمتد أولاً ، فأنت على ما يرام. يمكنك أن تؤكد ذلك من خلال بناء الكائن الآخر قبل "كائن A". طالما تم الإعلان عن كلا الكائنين في نفس وحدة التجميع ، سيتم تهيئته بالترتيب الذي يظهران في المصدر ، وتم تدميره بالترتيب المعاكس.

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

إنه جزء من الاختراق ، لكنني سأضيف بعض المنازل الثابتة لتتبع ترتيب التهيئة DE ثم الكائن الذي ينتهي به المطاف أخيرًا يقوم بالتنظيف حتى لو لم يكن المالك.

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