c++ - هل حذف استدعاء destructor؟




memory-management (8)

لدي فئة (A) يستخدم تخصيص ذاكرة كومة لأحد الحقول الخاصة به. يتم إنشاء مثيل للفئة A وتخزينها كحقل مؤشر في فئة أخرى (B).

عندما انتهيت من الكائن B ، أتصل بحذف ، والذي أفترض أنه يدعو destructor ... ولكن هل هذا استدعاء destructor في الفئة A كذلك؟

تصحيح:

من الإجابات ، أخذ ذلك (يرجى تعديله إذا كان غير صحيح):

  1. delete مثيل B المكالمات B :: ~ B ()؛
  2. الذي يستدعي A::~A();
  3. and A::~A يجب delete كافة المتغيرات الخاصة بـ A المخصصة بشكل صخري؛
  4. وأخيرًا ، يتم إرجاع كتلة الذاكرة التي تخزن مثيل B إلى الكومة - عندما تم استخدام جديد ، فقد خصصت أولاً كتلة من الذاكرة في الكومة ، ثم استدعت المنشئات لتهيئتها ، والآن بعد أن تم استدعاء جميع عناصر التدمير لإنهاء الكائن حظر المكان الذي يتم إرجاع الكائن إليه إلى الكومة.

إذا كان لديك مؤشر عادي ( A* ) ، فلن يتم استدعاء المدمر (ولن يتم تحرير الذاكرة للمثيل A ) ، إلا إذا قمت delete بشكل صريح في B 'destructor. إذا كنت تريد التدمير التلقائي ننظر إلى المؤشرات الذكية مثل auto_ptr .


سيتم استدعاء destructor للكائن من الفئة A فقط إذا تم استدعاء الحذف لهذا الكائن. تأكد من حذف هذا المؤشر في destructor من فئة B.

للحصول على مزيد من المعلومات حول ما يحدث عند استدعاء حذف على كائن ، راجع: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9


عند استدعاء حذف على مؤشر تم تخصيصه بواسطة جديد ، سيتم استدعاء destructor للكائن المشار إليه.

A * p = new A;

delete p;    // A:~A() called for you on obkect pointed to by p

كنت أتساءل لماذا لم يتم استدعاء destructor صفي. كان السبب أنني نسيت أن تتضمن تعريفًا لتلك الفئة (#include "class.h"). لم يكن لدي سوى تصريح مثل "الفئة أ" ؛ وكان المترجم سعيدًا به ودعني أطلب "حذف".


لا لن يطلق عليه destructor للفئة A ، يجب عليك الاتصال به بشكل صريح (مثل PoweRoy قال) ، حذف السطر "حذف ptr؛" في سبيل المثال للمقارنة ...

  #include <iostream>

  class A
  {
     public:
        A(){};
        ~A();
  };

  A::~A()
  {
     std::cout << "Destructor of A" << std::endl;
  }

  class B
  {
     public:
        B(){ptr = new A();};
        ~B();
     private:
        A* ptr;
  };

  B::~B()
  {
     delete ptr;
     std::cout << "Destructor of B" << std::endl;
  }

  int main()
  {
     B* b = new B();
     delete b;
     return 0;
  }

لديك شيء من هذا القبيل

class B
{
   A * a;
}
B * b = new B;
b->a = new A;

إذا قمت بعد ذلك باستدعاء delete b; ، لا يحدث أي شيء ، ولديك تسرب للذاكرة. تحاول تذكر delete b->a; ليس حلا جيدا ، ولكن هناك بضعة آخرين.

B::~B() {delete a;}

هذا هو destructor ل B الذي سيحذف. (إذا كانت القيمة 0 ، فهذا الحذف لا يفعل شيئًا. إذا لم تكن القيمة 0 ولكنها لا تشير إلى الذاكرة من جديد ، فستحصل على تلف في كومة الذاكرة المؤقتة.)

auto_ptr<A> a;
...
b->a.reset(new A);

بهذه الطريقة لا يكون لديك كمؤشر ، بل بالأحرى <auto_ptr <> (<shared_ptr <> auto_ptr ستقوم كذلك ، أو غيرها من المؤشرات الذكية) ، ويتم حذفها تلقائيًا عندما تكون b.

أي من هاتين الطريقتين تعمل بشكل جيد ، ولقد استخدمت كلاهما.


يدعى "destructor" ، وليس "deconstructor".

داخل المدمر لكل فئة ، يجب عليك حذف جميع المتغيرات الخاصة بالأعضاء الأخرى التي تم تخصيصها بأخرى جديدة.

تحرير: لتوضيح:

قل لديك

struct A {}

class B {
    A *a;
public:
    B () : a (new A) {}
    ~B() { delete a; }
};

class C {
    A *a;
public:
    C () : a (new A) {}        
};

int main () {
    delete new B;
    delete new C;
}

تخصيص مثيل B ثم حذفه نظيف ، لأن ما يخصصه B داخليًا سيتم حذفه أيضًا في destructor.

ولكن الحالات من الفئة C سوف تتسبب في حدوث تسرب للذاكرة ، نظرًا لأنها تقوم بتخصيص مثيل A الذي لا يتم إطلاقه (في هذه الحالة ، لا يوجد لدى C حتى أداة destructor).


class B
{
public:
    B()
    {
       p = new int[1024];  
    }
    virtual ~B()
    {
        cout<<"B destructor"<<endl;
        //p will not be deleted EVER unless you do it manually.
    }
    int *p;
};


class D : public B
{
public:
    virtual ~D()
    {
        cout<<"D destructor"<<endl;
    }
};

عندما تفعل:

B *pD = new D();
delete pD;

سيتم استدعاء destructor فقط إذا كان الصف الأساسي الخاص بك يحتوي على الكلمة الأساسية الظاهرية.

ثم إذا لم يكن لديك destructor افتراضي فقط سوف يتم استدعاء ~ B (). ولكن لأن لديك destructor الظاهري ، سيتم استدعاء أول ~ D () ، ثم ~ B ().

لن يتم إلغاء تخصيص أي عضو من B أو D المخصصًا في الكومة ما لم تحذفها صراحةً. وحذفها سيدعو المدمر كذلك.







destructor