Hoe noem ik de destructor van de klas?

Ik heb een eenvoudige C++-code, maar ik weet niet hoe ik de destructor moet gebruiken:

class date {
public:
    int day;
    date(int m)
    {
        day =m;
    }
    ~date(){
    cout << "I wish you have entered the year \n" << day;    
    }
};
int main()
{
  date ob2(12);
  ob2.~date();
  cout << ob2.day;
  return 0;
}

De vraag die ik heb is, wat moet ik in mijn destructorcode schrijven, dat na het aanroepen van de destructor, het de dayvariabelezal verwijderen?


Antwoord 1, autoriteit 100%

Je moet je destructor niet expliciet bellen.

Als je je object op de stapel maakt (zoals je deed), heb je alleen het volgende nodig:

int main()
{
  date ob2(12);
  // ob2.day holds 12
  return 0; // ob2's destructor will get called here, after which it's memory is freed
}

Als je je object op de heap maakt, moet je je klasse deletevoordat de destructor wordt aangeroepen en het geheugen wordt vrijgemaakt:

int main()
{
  date* ob2 = new date(12);
  // ob2->day holds 12
  delete ob2; // ob2's destructor will get called here, after which it's memory is freed
  return 0;   // ob2 is invalid at this point.
}

(Als u in dit laatste voorbeeld de verwijdering niet aanroept, leidt dit tot geheugenverlies.)

Beide manieren hebben hun voor- en nadelen. De manier van stapelen is ZEER snel met het toewijzen van het geheugen dat het object in beslag zal nemen en je hoeft het niet expliciet te verwijderen, maar de stapel heeft beperkte ruimte en je kunt die objecten niet gemakkelijk, snel en netjes verplaatsen.

De heap heeft de voorkeur om het te doen, maar als het op prestaties aankomt, is het traag om toe te wijzen en heb je te maken met pointers. Maar je hebt veel meer flexibiliteit met wat je met je object doet, het is veel sneller om verder met pointers te werken en je hebt meer controle over de levensduur van het object.


Antwoord 2, autoriteit 98%

Het is zelden nodig om de destructor expliciet aan te roepen. In plaats daarvan wordt de destructor aangeroepen wanneer een object wordt vernietigd.

Voor een object zoals ob2dat een lokale variabele is, wordt het vernietigd wanneer het buiten bereik gaat:

int main() 
{ 
    date ob2(12); 
} // ob2.~date() is called here, automatically!

Als u een object dynamisch toewijst met behulp van new, wordt de destructor aangeroepen wanneer het object wordt vernietigd met behulp van delete. Als je een statisch object hebt, wordt de destructor aangeroepen wanneer het programma wordt beëindigd (als het programma normaal wordt beëindigd).

Tenzij u iets dynamisch maakt met behulp van new, hoeft u niets expliciets te doen om het op te schonen (dus wanneer bijvoorbeeld ob2wordt vernietigd, van zijn lidvariabelen, inclusief day, worden vernietigd). Als je iets dynamisch maakt, moet je ervoor zorgen dat het wordt vernietigd als je er klaar mee bent; het beste is om een ​​zogenaamde “slimme aanwijzer” te gebruiken om ervoor te zorgen dat deze opschoning automatisch wordt afgehandeld.


Antwoord 3, autoriteit 100%

U hoeft de destructor niet expliciet aan te roepen. Dit gebeurt automatisch aan het einde van het bereik van het object ob2, d.w.z. aan het einde van de functie main.

Bovendien, aangezien het object automatische opslag heeft, hoeft de opslag niet te worden verwijderd. Ook dit gebeurt automatisch aan het einde van de functie.

Het handmatig aanroepen van destructors is bijna nooit nodig (alleen in bibliotheekcode op laag niveau) en het handmatig verwijderen van geheugen is alleen nodig (en alleen een geldige bewerking) wanneer het geheugen eerder is verkregen met behulp van new(wanneer u werkt met aanwijzers).

Aangezien handmatig geheugenbeheer gevoelig is voor lekken, probeert moderne C++-code newen deletehelemaal niet expliciet te gebruiken. Wanneer het echt nodig is om newte gebruiken, dan wordt een zogenaamde slimme aanwijzer gebruikt in plaats van een gewone aanwijzer.


Antwoord 4, autoriteit 36%

Alleen in zeer specifieke omstandigheden hoeft u de vernietiger rechtstreeks te bellen. Standaard wordt de destructor door het systeem aangeroepen wanneer u een variabele voor automatische opslag maakt en deze buiten het bereik valt of wanneer een object dat dynamisch is toegewezen met newwordt vernietigd met delete.

struct test {
   test( int value ) : value( value ) {}
   ~test() { std::cout << "~test: " << value << std::endl; }
   int value;
};
int main()
{
   test t(1);
   test *d = new t(2);
   delete d;           // prints: ~test: 2
}                      // prints: ~test: 1 (t falls out of scope)

Voor de volledigheid (dit zou in het algemeen niet moeten worden gebruikt) is de syntaxis om de destructor aan te roepen vergelijkbaar met een methode. Nadat de destructor is uitgevoerd, is het geheugen niet langer een object van dat type (moet worden behandeld als onbewerkt geheugen):

int main()
{
   test t( 1 );
   t.~test();            // prints: ~test: 1
                         // after this instruction 't' is no longer a 'test' object
   new (&t) test(2);     // recreate a new test object in place
}                        // test falls out of scope, prints: ~test: 2

Opmerking: na het aanroepen van de destructor op t, is die geheugenlocatie niet langer een test, dat is de reden voor recreatievan de object door middel van de plaatsing nieuw.


Antwoord 5, autoriteit 7%

Ook al lijkt de destructor iets dat je moet aanroepen om je object te verwijderen of te “vernietigen” als je klaar bent met het gebruik ervan, het is niet de bedoeling dat je het op die manier gebruikt.

De destructor is iets dat automatisch wordt aangeroepen wanneer uw object buiten bereik gaat, dat wil zeggen, wanneer de computer de “accolades” verlaat waarin u uw object heeft geïnstantieerd. In dit geval, wanneer u main() verlaat. Je wilt het niet zelf noemen.


Antwoord 6, autoriteit 7%

U kunt hier in de war raken door ongedefinieerd gedrag. De C++-standaard heeft geen regels over wat er gebeurt als je een object gebruikt nadat de destructor is uitgevoerd, want dat is ongedefinieerd gedrag en daarom kan de implementatie alles doen wat het wil. Meestal doen compilerontwerpers niets speciaals voor ongedefinieerd gedrag, en wat er dus gebeurt, is een artefact van welke andere ontwerpbeslissingen werden genomen. (Dit kan soms rare resultaten opleveren.)

Daarom, als je de destructor eenmaal hebt uitgevoerd, heeft de compiler geen verdere verplichting met betrekking tot dat object. Als je er niet meer naar verwijst, maakt het niet uit. Als je ernaar verwijst, is dat ongedefinieerd gedrag, en vanuit het oogpunt van de standaard doet het er niet toe, en aangezien de standaard niets zegt, zullen de meeste compilerontwerpers zich geen zorgen maken over wat het programma doet.

In dit geval is het het gemakkelijkst om het object onaangeroerd te laten, aangezien het geen middelen vasthoudt, en de opslag is toegewezen als onderdeel van het opstarten van de functie en zal niet worden teruggevorderd totdat de functie wordt afgesloten . Daarom blijft de waarde van het gegevenslid hetzelfde. Het natuurlijke dat de compiler moet doen als hij ob2.dayleest, is toegang krijgen tot de geheugenlocatie.

Zoals elk ander voorbeeld van ongedefinieerd gedrag, kunnen de resultaten veranderen onder elke verandering in omstandigheden, maar in dit geval zullen ze dat waarschijnlijk niet doen. Het zou leuk zijn als compilers meer gevallen van ongedefinieerd gedrag zouden opvangen en diagnostiek zouden uitvoeren, maar het is niet mogelijk voor compilers om al het ongedefinieerde gedrag te detecteren (sommige gebeurt tijdens runtime) en vaak controleren ze niet op gedrag dat ze niet denken waarschijnlijk.


Antwoord 7

In dit geval hoeft uw destructor de dagvariabele niet te verwijderen.

Je hoeft alleen het geheugen te verwijderen dat je hebt toegewezen aan nieuw.

Hier ziet u hoe uw code eruit zou zien als u new en delete zou gebruiken om het aanroepen van de destructor te activeren

class date {
  public: int* day; 
  date(int m) { 
      day = new int;
      *day = m; 
  }
  ~date(){ 
      delete day;
      cout << "now the destructor get's called explicitly";
  } 
};
int main() { 
  date *ob2 = new date(12); 
  delete ob2;
  return 0; 
}

LEAVE A REPLY

Please enter your comment!
Please enter your name here

3 + 1 =

Other episodes