سؤال

كنت مناقشة مع بعض الزملاء حول ما يحدث عند رمي استثناء في فئة مخصصة ديناميكيا. وأنا أعلم ذلك malloc يحصل دعا، ثم منشئ الفصل. المنشئ لا يعود أبدا، فماذا يحدث malloc?

النظر في المثال التالي:

class B
{
public:
    B()
    {
        cout << "B::B()" << endl;
        throw "B::exception";
    }

    ~B()
    {
        cout << "B::~B()" << endl;          
    }
};

void main()
{
    B *o = 0;
    try
    {
        o = new B;
    }
    catch(const char *)
    {
        cout << "ouch!" << endl;
    }
}

ماذا يحدث للذاكرة malloced o, ، هل تسرب؟ هل يصطاد CRT باستثناء المنشئ إلغاء الذاكرة؟

هتافات!
ثري

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

المحلول

دعوة إلى

new B();

يحل في شيئين:

  • تخصيص مع المشغل new (xxx) B())
  • استدعاء المنشئ.

إذا رمي المنشئ، يتم استدعاء عامل المشغل المقابل. الحالة التي يكون فيها الحذف المقابل هو موضع واحد هو الحالة الوحيدة التي يتم فيها استدعاء مشغل حذف الموضع بدون بناء جملة :: Operator (). delete x; أو delete[] x; لا تتصل بمشغل حذف المواضع وليس هناك بناء جملة مماثل للتنسيب الجديد للاتصال بهم.

لاحظ أنه في حين أن المدمر في B سوف ليس سيتم استدعاؤه، سيتم تدمير Subobjects تم إنشاؤه بالفعل (أعضاء أو فئات B و B) قبل دعوة إلى حذف المشغل. المنشئ الذي لا يسمى هو واحد ل B.

نصائح أخرى

عند طرح استثناء من المنشئ، يتم إصدار الذاكرة المخصصة بواسطة NEW، ولكن لا يسمى Destructor of Class B.

في هذه الحالة، لا يتم تصميم كائنك، O، في الواقع، ويتم تحرير الذاكرة المخصصة بواسطة NEW. على هذا النحو، لا يسمى المدمر. لذلك لا تحتاج إلى الاتصال:

delete o;

نمط تصميم مثير للاهتمام هو raii - اكتساب الموارد هو التهيئة. في هذا النمط، تستخدم منشئ لتغليف الاستحواذ على مورد، وإصدار المورد في المدمر. إذا كان لا يمكن الحصول على المورد، فأنت ترمي في المنشئ - مثل مثالك. وبالتالي إذا كان لديك كائن صالح، يكون لديك المورد.

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

http://en.wikipedia.org/wiki/resource_accisition_is_initialization.

من المعيار C ++ 2003 5.3.4 / 17 - جديد:

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

لذلك قد يكون هناك أو قد لا يكون هناك تسرب - هذا يعتمد على ما إذا كان يمكن العثور على عباءة مناسبا (وهذا هو الحال عادة، ما لم يتم تجاوز المشغل الجديد / حذف). في حالة وجود مزاولة مناسب، يكون المحول البرمجي مسؤولا للأسلاك في مكالمة لها إذا يلقي المنشئ.

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

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