Wie verwende ich RAII, um Ressourcen der Klasse zu erwerben?

7

Es gibt ein Beispiel, das zeigt, dass RAII auf diese Weise verwendet wird:

%Vor%

ist sicher. aber meine Frage ist: Was passiert, wenn eine Ausnahme in p=fopen(n,a); geworfen wird, dann wird Speicher, der i zugewiesen ist, nicht zurückgegeben. Ist das richtig anzunehmen, dass RAII Ihnen sagt, dass jedes Mal, wenn Sie X als sicher haben wollen, alle von X erworbenen Ressourcen auf dem Stack zugewiesen werden müssen? Und wenn X.a erstellt wird, müssen Ressourcen von a ebenfalls auf den Stack gelegt werden? und nochmal, und wieder, ich meine schließlich, wenn es eine Ressource auf dem Haufen gibt, wie es mit RAII gehandhabt werden könnte? Wenn es nicht meine Klasse ist, d. H.

    
Fred Larson 24.04.2013, 19:07
quelle

6 Antworten

1

Wenn Sie dies als eine intellektuelle Übung behandeln, bei der Sie std::vector nicht verwenden möchten, müssen Sie Ihre Klassen aufteilen, damit sie eine einzige Verantwortung tragen. Hier ist meine "Integer Array" -Klasse. Seine Aufgabe ist es, den Speicher für ein Integer-Array zu verwalten.

%Vor%

Hier ist meine Datei-Handling-Klasse. Ihre Aufgabe ist es, ein FILE* zu verwalten.

%Vor%

Beachten Sie, dass ich meinen Konstruktionsfehler in eine Ausnahme umwandle; fp_ ist ein gültiger Dateizeiger. Es ist eine Invariante, die ich beibehalten möchte, also bricht ich die Konstruktion ab, wenn ich diese Invariante nicht setzen kann.

Jetzt ist es einfach, File_ptr exception safe zu machen, und die Klasse benötigt keine komplexe Ressourcenverwaltung.

%Vor%

Beachten Sie das Fehlen eines vom Benutzer deklarierten Destruktors, Kopierzuweisungsoperators oder Kopierkonstruktors. Ich kann die Reihenfolge der Mitglieder tauschen und in beiden Fällen ist es egal, welcher Konstruktor wirft.

    
Charles Bailey 25.04.2013, 11:11
quelle
11

Der springende Punkt von RAII ist, KEINE Ressourcen (wie das int -array) an dangelnden Zeigern zuzuweisen. Verwenden Sie stattdessen std::vector oder weisen Sie den Array-Zeiger einer Art std::unique_ptr zu. Auf diese Weise werden die Ressourcen zerstört, wenn Ausnahmen auftreten.

Und nein, Sie müssen STL nicht verwenden, aber um RAII zu verwenden, müssen die niedrigsten Basisressourcen (wie Heap-zugewiesene Arrays) auch mit RAII erstellt werden, und der einfachste Weg dazu ist Verwenden Sie STL, anstatt eigene Smart-Pointer oder Vektoren zu schreiben.

    
Excelcius 24.04.2013 19:32
quelle
3

Wenn eine Ausnahme nach dem new auftritt, müssen Sie die Ausnahme abfangen und den Zeiger im Konstruktor löschen und dann erneut werfen. In diesem Fall wird der Destruktor nicht aufgerufen, da das Objekt niemals konstruiert wird.

andernfalls, wenn i ein std :: vector ist, wird es automatisch bereinigt

    
yngccc 24.04.2013 19:15
quelle
3

Eine Möglichkeit, dies zu umgehen, besteht darin, alles, was durch eine Ausnahme ungültig gemacht werden könnte, in eine lokale Variable zu setzen, die selbst RAII verwendet, und sie dann am Ende den Mitgliedern zuzuweisen, wenn es sicher ist.

%Vor%

Weitere Informationen finden Sie unter Ausnahmesicherheit .

    
Mark Ransom 24.04.2013 19:47
quelle
2

Wenn du weißt, dass es geworfen wird, lege es in ein try-catch .

%Vor%     
andre 24.04.2013 19:21
quelle
1
%Vor%     
Smalti 24.04.2013 19:53
quelle

Tags und Links