The destructor
A constructor runs when an object is born. A destructor runs when it dies – when it goes out of scope or is deleted. Its name is the class name with a ~ (tilde) in front:
#include <iostream>
#include <string>
using namespace std;
class Guest {
string name;
public:
Guest(string n) : name(n) {
cout << name << " arrives\n";
}
~Guest() {
cout << name << " leaves\n";
}
};
int main() {
Guest a("Ana");
{
Guest b("Ben");
cout << "Party inside the braces\n";
} // b goes out of scope here
cout << "Back in main\n";
return 0;
} // a goes out of scope hereOutput
Ana arrives Ben arrives Party inside the braces Ben leaves Back in main Ana leaves
Notice the order: Ben leaves as soon as his { } block ends. Ana leaves at the end of main. Objects are destroyed in the reverse order they were created.
RAII: let objects clean up after themselves
RAII stands for Resource Acquisition Is Initialization – a long name for a simple, powerful idea: get a resource in the constructor, give it back in the destructor. Then you can never forget to clean up.
#include <iostream>
using namespace std;
class IntBuffer {
int* data;
int size;
public:
IntBuffer(int n) : data(new int[n]), size(n) {
cout << "Reserved " << size << " ints\n";
}
~IntBuffer() {
delete[] data;
cout << "Freed " << size << " ints\n";
}
int& at(int i) { return data[i]; }
};
int main() {
IntBuffer buf(3);
buf.at(0) = 10;
buf.at(1) = 20;
cout << buf.at(0) + buf.at(1) << "\n";
return 0; // no delete needed: ~IntBuffer() does it
}Output
Reserved 3 ints 30 Freed 3 ints
Think of it like this: RAII is like a hotel room key card that is automatically cancelled when you check out. You don't have to remember to cancel it; leaving does it for you.
Remember:
vector,stringand the file streams all use RAII. That's why you never have to free them yourself.