What a destructor is
A destructor is a method that runs when an object is destroyed, to release resources (files, network connections, memory).
- C++ has destructors written as
~ClassName(), and they run when the object goes out of scope or is deleted. - Java and Python have no destructors in the C++ sense. Memory is reclaimed automatically by the garbage collector (see 3.2.2). To release resources such as files, Java uses try-with-resources and the
AutoCloseableinterface, or an explicitclose()method. The oldfinalize()method is deprecated and must not be used.
class Report implements AutoCloseable {
Report() { System.out.println("Report opened"); }
@Override
public void close() { System.out.println("Report closed"); }
}
try (Report r = new Report()) {
System.out.println("Working...");
} // close() is called automatically hereOutput: Report opened, Working..., Report closed.
For comparison, here is the same idea in C++. The destructor runs automatically, at a predictable moment, when the object goes out of scope:
#include <iostream>
using namespace std;
class Report {
public:
Report() { cout << "Report opened" << endl; }
~Report() { cout << "Report closed" << endl; } // destructor
};
int main() {
Report r; // constructor runs
cout << "Working..." << endl;
return 0;
} // r goes out of scope: destructor runsWhy releasing resources matters
Memory is not the only thing an object can hold. Objects often hold resources that belong to the operating system or to another program: an open file, a database connection, a network socket or a printer. There is only a limited number of these. If a program opens files and never closes them, it eventually cannot open any more. A database server may refuse new connections, and data written to a file may never actually be saved to disk.
The garbage collector frees memory, but you cannot know when it will run (see 3.2.2). Waiting for it to close a file is not good enough. So in Java you close resources yourself, at a moment you choose.
How try-with-resources works
try (Report r = new Report()) { // the resource is opened here
r.write();
} // r.close() is called here, automatically- The class must implement the
AutoCloseableinterface, which means it has aclose()method. - When the
tryblock ends, Java callsclose()automatically: whether the block finishes normally, returns early or throws an exception. - You can open several resources in one
try (...). They are closed in the reverse order to the one they were opened in.
Before Java 7, programmers had to call close() in a finally block. That approach still works, but it is longer and easy to get wrong.
C++ destructors and RAII
In C++, a destructor runs at an exact, predictable moment: when a local object goes out of scope at the closing }, or when delete is used on an object created with new. C++ programmers use this to tie a resource to an object's lifetime: the constructor opens the resource and the destructor closes it. This idea is called RAII (Resource Acquisition Is Initialisation). Java's try-with-resources gives the same safety in a different way.
| Language | Memory freed by | Resources released by |
|---|---|---|
| C++ | The programmer (delete) or automatically at the end of scope | The destructor ~ClassName() |
| Java | The garbage collector | close(), usually through try-with-resources |
| Python | Automatic (reference counting and a garbage collector) | with statements and close() |
Remember
- Java has no destructors; the garbage collector frees memory at a time you cannot predict.
- Release files, connections and other resources yourself, with
close()or try-with-resources. - In C++, a destructor runs automatically when an object goes out of scope or is deleted.