সাবক্লাসের পয়েন্টারে মুছে ফেলা কি বেস ক্লাসের ডেস্ট্রাক্টরকে কল করে?


165

আমার একটি রয়েছে class Aযা এর একটি ক্ষেত্রের জন্য একটি হিপ মেমরির বরাদ্দ ব্যবহার করে। ক্লাস এ তাত্ক্ষণিকভাবে এবং অন্য শ্রেণিতে পয়েন্টার ক্ষেত্র হিসাবে সংরক্ষণ করা হয় ( class B

আমি যখন ক্লাস বি এর একটি অবজেক্টের সাথে সম্পন্ন হয়েছি তখন আমি কল deleteকরি যা আমি ডিস্ট্রাক্টরকে কল করি ... তবে এটি কি ক্লাস এ এর ​​ডেস্ট্রাক্টরকে কল করে?

সম্পাদনা:

উত্তরগুলি থেকে, আমি এটি নিচ্ছি (দয়া করে ভুল হলে সম্পাদনা করুন):

  1. delete বি এর উদাহরণ বি কে বি :: ~ বি () বলে;
  2. যা কল A::~A();
  3. A::~A স্পষ্টভাবে deleteএ অবজেক্টের সমস্ত হিপ-বরাদ্দকৃত সদস্য ভেরিয়েবলের উচিত ;
  4. পরিশেষে মেমরি ব্লক স্টোরেজ করে বলা হয়েছিল যে ক্লাস বি এর উদাহরণটি গাদাতে ফিরে আসে - যখন নতুন ব্যবহৃত হয়েছিল, প্রথমে এটি স্তূপে মেমরির একটি ব্লক বরাদ্দ দেয়, তারপরে এটির আরম্ভের জন্য কনস্ট্রাক্টরদের অনুরোধ করা হয়েছিল, এখন সমস্ত ডিস্ট্রাক্টর অবজেক্টটি চূড়ান্ত করার জন্য অনুরোধ করা হয়েছে। যেখানে অবজেক্টটি রক্ষিত ছিল সেটিকে ব্লক করে ফেলা হয়।

উত্তর:


183

আ এর ডেস্ট্রাক্টর চলবে যখন এর জীবনকাল শেষ হবে। আপনি যদি এর স্মৃতিটি মুক্ত করতে চান এবং ধ্বংসকারী চালিত হন তবে এটি গাদাতে বরাদ্দ করা থাকলে আপনাকে এটি মুছতে হবে। যদি এটি স্ট্যাকের জন্য বরাদ্দ করা হয় তবে এটি স্বয়ংক্রিয়ভাবে ঘটে (যেমন যখন এটি সুযোগের বাইরে চলে যায়; RAII দেখুন)। যদি এটি কোনও শ্রেণীর সদস্য হয় (কোনও পয়েন্টার নয়, তবে একটি সম্পূর্ণ সদস্য), তবে এটি যখন অন্তর্ভুক্ত বস্তুটি ধ্বংস হয়ে যাবে তখন এটি ঘটবে।

class A
{
    char *someHeapMemory;
public:
    A() : someHeapMemory(new char[1000]) {}
    ~A() { delete[] someHeapMemory; }
};

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

class C
{
    A Amember;
public:
    C() : Amember() {}
    ~C() {} // A is freed / destructed automatically.
};

int main()
{
    B* BPtr = new B();
    delete BPtr; // Calls ~B() which calls ~A() 
    C *CPtr = new C();
    delete CPtr;
    B b;
    C c;
} // b and c are freed/destructed automatically

উপরের উদাহরণে, প্রতিটি মোছা এবং মোছা [] প্রয়োজন। এবং কোনও মুছার দরকার নেই (বা সত্যই ব্যবহৃত হতে সক্ষম) যেখানে আমি এটি ব্যবহার করি নি।

auto_ptr, unique_ptrএবং shared_ptrইত্যাদি ... এই আজীবন পরিচালনাকে আরও সহজ করার জন্য দুর্দান্ত:

class A
{
    shared_array<char> someHeapMemory;
public:
    A() : someHeapMemory(new char[1000]) {}
    ~A() { } // someHeapMemory is delete[]d automatically
};

class B
{
    shared_ptr<A> APtr;
public:
    B() : APtr(new A()) {}
    ~B() {  } // APtr is deleted automatically
};

int main()
{
    shared_ptr<B> BPtr = new B();
} // BPtr is deleted automatically

আমি অবাক হয়েছি যখন আপনি কেবল আংশিকভাবে মেমরিটি মুক্ত করেন (যেমন, ভুল পয়েন্টার ব্যবহার করে) ডেস্ট্রাক্টর বলা হয়
টম্যা জ্যাটো - মনিকা পুনরায় ইনস্টল করুন

পয়েন্টার মাত্র একটি সংখ্যা। এমনকি আপনি দুর্ঘটনাক্রমে এতে ++অপারেটরও ব্যবহার করতে পারেন । সুতরাং আমি অবাক হই যদি পয়েন্টার যে বর্গ ডাটা মাঝখানে পয়েন্টার এখনও প্রভাব আছে।
টোমা জাটো - মনিকা

2
@ টোমাজাটো: আপনি যদি এলোমেলো পয়েন্টারে ডিলিট কল করেন, তবে আপনার ক্ষতি হবে। এটি করার কোনও ভাল কারণ নেই। প্রকৃতপক্ষে, আপনি যদি ম্যানুয়ালি কোনও স্মার্ট পয়েন্টার ডেস্ট্রাক্টর ছাড়া অন্য কোথাও মুছে ফেলার কল করে থাকেন তবে আপনি সম্ভবত কেন স্মার্ট পয়েন্টার বা অন্য কোনও অবজেক্ট ম্যানেজার ব্যবহার করছেন না সে সম্পর্কে দ্বিতীয়বার দেখতে চান।
অন্ধকার

শেয়ারড_আরেই কেবল বুস্ট থেকে এসেছে, হ্যাঁ?
দ্রোঞ্জ

30

আপনি যখন নতুন দ্বারা বরাদ্দকৃত পয়েন্টারে কল মুছুন, তখন নির্দেশিত বস্তুর বিনষ্টকারীকে ডাকা হবে।

A * p = new A;

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

22

এটির নামকরণ করা হয়েছে "ডিস্ট্রাক্টর", "ডিকনস্ট্রাক্টর" নয়।

প্রতিটি শ্রেণীর ডেস্ট্রাক্টরের অভ্যন্তরে, আপনাকে নতুন সহ বরাদ্দ করা সমস্ত অন্যান্য সদস্য ভেরিয়েবলগুলি মুছতে হবে।

সম্পাদনা করুন: স্পষ্ট করতে:

বলুন তো আছে

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;
}

বি এর একটি উদাহরণ বরাদ্দ করা এবং তারপরে মুছে ফেলা পরিষ্কার, কারণ বি অভ্যন্তরীণভাবে যা বরাদ্দ করে তাও ডিস্ট্রাক্টরে মুছে ফেলা হবে।

তবে সি শ্রেণীর উদাহরণগুলি মেমরি ফাঁস করবে, কারণ এটি এ এর ​​একটি উদাহরণ বরাদ্দ করে যা এটি প্রকাশ করে না (এই ক্ষেত্রে সিতে কোনও ধ্বংসকারীও নেই)।


5

যদি আপনার একটি সাধারণ পয়েন্টার থাকে ( A*) থাকে তবে ডেস্ট্রাক্টরকে ডাকা হবে না (এবং Aউদাহরণস্বরূপ মেমরিটিও মুক্তি পাবে না) যদি না আপনি deleteস্পষ্টভাবে Bডেস্ট্রাক্টর না করে থাকেন। আপনি যদি স্বয়ংক্রিয় ধ্বংস চান তবে স্মার্ট পয়েন্টারগুলিতে দেখুন auto_ptr


4

আপনার নিজেরাই বি এর ডেস্ট্রাক্টরে মুছে ফেলা উচিত


4
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;

আপনার বেস ক্লাসে ভার্চুয়াল কীওয়ার্ড থাকলেই ডেস্ট্রাক্টরকে ডাকা হবে।

তারপরে যদি আপনার ভার্চুয়াল ডেস্ট্রাক্টর না থাকে তবে কেবল ~ বি () কল করা হবে। তবে যেহেতু আপনার ভার্চুয়াল ডেস্ট্রাক্টর রয়েছে, তাই প্রথমে ~ D () বলা হবে, তারপরে ~ বি ()।

হিটে বরাদ্দ করা বি বা ডি এর কোনও সদস্যই যদি আপনি তাদের স্পষ্টভাবে মুছে না দেন তবে তা হ্রাস করা হবে না। এবং এগুলি মুছে ফেলা তাদের ধ্বংসকারীদেরও কল করবে call


1

আপনার মত কিছু আছে

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

আপনি যদি তখন কল করেন তবে delete b;ক এর কিছুই হয় না এবং আপনার স্মৃতি ফাঁস হয়। মনে রাখার চেষ্টা করা delete b->a;ভাল সমাধান নয়, তবে আরও কয়েকজন রয়েছেন।

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

এটি বি এর জন্য একটি ডেস্ট্রাক্টর যা একটি মুছে ফেলবে। (যদি একটি 0 হয়, তবে মোছা কিছুই করে না a

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

এইভাবে আপনার পয়েন্টার হিসাবে কোনওটি নেই, বরং একটি অটো_পিটার <> (শেয়ার্ড_প্রে <<> পাশাপাশি করবে, বা অন্য স্মার্ট পয়েন্টারগুলি করবে), এবং খ হলে তা স্বয়ংক্রিয়ভাবে মুছে ফেলা হবে।

এই উপায়গুলির যে কোনও একটি ভাল কাজ করে, এবং আমি উভয় ব্যবহার করেছি।


1

আমি ভাবছিলাম কেন আমার ক্লাসের ডেস্ট্রাক্টর ডাকা হয়নি? কারণটি হ'ল আমি class শ্রেণীর সংজ্ঞা অন্তর্ভুক্ত করতে ভুলে গিয়েছিলাম (# অন্তর্ভুক্ত "class.h")। আমার কেবলমাত্র "ক্লাস এ" এর মতো ঘোষণা ছিল; এবং সংকলক এতে খুশি হয়েছিল এবং আমাকে "মুছুন" কল করতে দিন।


সংকলক সতর্কতা স্তর বাড়ান
ফিল 1970

0

না। পয়েন্টার মোছা হবে। আপনার বি এর ডেস্ট্রাক্টরের স্পষ্টে মুছে ফেলা উচিত call


আমি এটি করছি, আমার প্রশ্নটি কি বিনষ্টকারী বলা হয়?
নিক বোল্টন

0

শ্রেণি A এর অবজেক্টের জন্য ডেস্ট্রাক্টর কেবল তখনই ডাকা হবে যখন সেই বস্তুর জন্য মুছুন। বি ক্লাসের ডেস্ট্রাক্টরে সেই পয়েন্টারটি মুছে ফেলার বিষয়ে নিশ্চিত হন

মুছে ফেলা হলে কোন বস্তুটিতে ডাকা হলে কী হয় সে সম্পর্কে আরও কিছু তথ্যের জন্য দেখুন: http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.9


0

না এটি ক্লাস এ এর ​​জন্য ডেস্ট্রাক্টরকে ডাকবে না, আপনার এটিকে স্পষ্টভাবে কল করা উচিত (যেমন পভরোয় বলেছেন), লাইন মুছে ফেলুন 'পিটিআর মুছুন;' উদাহরণস্বরূপ তুলনা ...

  #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;
  }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.