?
Kleiner Nachtrag noch zu RAII:
Wenn du mit Java 7 schon gearbeitet hast, kennst du etwas ähnliches wie RAII vom AutoCloseable-Interface. Wenn ich das richtig im Kopf habe, ist die Syntax da
try(
Ressourcenverwalter obj = new Ressourcenverwalter(); // implements AutoCloseable
) {
dieseFunktionKannEineExceptionWerfen();
} // obj.close() wird hier aufgerufen, auch wenn eine Exception geworfen wird.
Es ist kein Zufall, dass die Java-Leute den Mechanismus in die Exception-Handling-Syntax eingebunden haben; auch in C++ ist RAII der bevorzugte Mechanismus, um Exceptionsicherheit herzustellen. Zum Beispiel
void foo() {
std::lock_guard<std::mutex> lock(mein_mutex);
das_hier_kann_exceptions_werfen();
} // lock wird hier zerstört, mein_mutex dadurch wieder aufgeschlossen.
Vergleiche das mit
void foo() {
try {
mein_mutex.lock();
das_hier_kann_exceptions_werfen();
mein_mutex.unlock();
} catch(...) {
mein_mutex.unlock();
throw;
}
}
Eklig, oder? Und damit wäre es auch leichter, sich zu vertun. Den gleichen Effekt hast du mit nacktem new:
// Falsch:
void foo() {
int *arr = new int[10];
dies_kann_eine_exception_werfen();
delete[] arr; // Wenn eine Exception geworfen wird, wird das nie aufgerufen.
}
// Eklig:
void foo() {
int *arr = new int[10];
try {
dies_kann_eine_exception_werfen();
delete[] arr;
} catch(...) {
delete[] arr;
throw;
}
}
// Richtig:
void foo() {
std::vector<int> vec(10);
dies_kann_eine_exception_werfen();
} // vec wird hier zerstört und sein Speicher freigegeben, auch wenn eine Exception geworfen wurde.
In gutem C++-Code sieht man solche Dinge andauernd.