Chiama un distruttore esplicitamente in C++

Jinku Hu 12 ottobre 2023
Chiama un distruttore esplicitamente in C++

Questo articolo spiegherà diversi metodi su come chiamare un distruttore in modo esplicito in C++.

Usa la notazione obj.~ClassName() per chiamare esplicitamente una funzione distruttore

I distruttori sono funzioni speciali che vengono eseguite quando un oggetto esce automaticamente dall’ambito o viene eliminato da una chiamata esplicita dell’utente. Notare che queste funzioni sono generalmente utilizzate per liberare le risorse usate dall’oggetto dato. Anche se un distruttore può essere chiamato esplicitamente come funzione membro, non è necessario farlo. Nella maggior parte dei casi, in cui i membri dei dati della classe vengono allocati dinamicamente, può portare a una doppia liberazione delle risorse. Quest’ultimo scenario di solito produce una chiusura anomala del programma.

Nell’esempio seguente, mostriamo la nostra classe definita chiamata - MyClass, che ha due costruttori e un metodo integrato per recuperare il valore dell’unico membro dei dati. Anche il distruttore è definito, e con i costruttori, stampano i messaggi corrispondenti nel flusso cout per rendere più facile per noi indagare sul comportamento.

Si noti che il seguente codice di esempio stampa due messaggi del distruttore, uno dei quali viene attivato dalla chiamata esplicita dell’utente e l’altro viene chiamato automaticamente all’uscita dal programma. Sebbene, se il membro di dati MyClass fosse stato assegnato con l’operatore new nel costruttore, questo esempio avrebbe portato a una chiusura anomala del programma, probabilmente un doppio errore.

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

class MyClass {
 public:
  explicit MyClass(string s) : str(std::move(s)) {
    cout << "Constructor 1 executed\n";
  }

  MyClass(const MyClass& s) : str(string(s.str)) {
    cout << "Constructor 2 executed\n";
  }

  ~MyClass() { cout << "Destructor executed\n"; }

  string& getString() { return str; };

 private:
  string str;
};

int main() {
  MyClass str1("Hello There! ");

  cout << endl;
  cout << "str1: " << str1.getString() << endl;
  cout << endl;

  str1.~MyClass();

  return EXIT_SUCCESS;
}

Produzione:

Constructor 1 executed

str1: Hello There!

Destructor executed
Destructor executed

In alternativa, possiamo vedere che la seguente versione del codice attiva lo stesso numero di funzioni costruttore / distruttore, che è essenzialmente l’idea alla base di questo concetto. Quindi, anche se l’ultimo esempio funziona senza errori, non è consigliabile chiamare esplicitamente i distruttori.

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

class MyClass {
 public:
  explicit MyClass(string s) : str(std::move(s)) {
    cout << "Constructor 1 executed\n";
  }

  MyClass(const MyClass& s) : str(string(s.str)) {
    cout << "Constructor 2 executed\n";
  }

  ~MyClass() { cout << "Destructor executed\n"; }

  string& getString() { return str; };

 private:
  string str;
};

int main() {
  MyClass str1("Hello There! ");
  MyClass str2(str1);

  cout << endl;
  cout << "str2: " << str2.getString() << endl;
  cout << endl;

  return EXIT_SUCCESS;
}

Produzione:

Constructor 1 executed
Constructor 2 executed

str2: Hello There!

Destructor executed
Destructor executed

Un altro caso da considerare è quando l’oggetto classe viene allocato con l’operatore new e prima dell’uscita del programma viene chiamato delete sullo stesso oggetto. Nota che l’ultima istruzione cout viene stampata dopo l’esecuzione della funzione descrittore, il che significa che il descrittore è stato invocato quando è stato chiamato l’operatore delete.

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

class MyClass {
 public:
  explicit MyClass(string s) : str(std::move(s)) {
    cout << "Constructor 1 executed\n";
  }

  MyClass(const MyClass& s) : str(string(s.str)) {
    cout << "Constructor 2 executed\n";
  }

  ~MyClass() { cout << "Destructor executed\n"; }

  string& getString() { return str; };
  string* getStringAddr() { return &str; };

 private:
  string str;
};

int main() {
  auto* str4 = new MyClass("Hello There! ");

  cout << endl;
  cout << "str4: " << str4->getString() << endl;
  cout << endl;

  delete str4;
  cout << "exiting" << endl;

  return EXIT_SUCCESS;
}

Produzione:

Constructor 1 executed

str4: Hello There!

Destructor executed
Autore: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn Facebook

Articolo correlato - C++ Class