Kein RAII - Kein Spaß
« | 19 Oct 2018 | »Wer “Resource Acquisition Is Initialization” - kurz RAII - nicht kennt, hat nicht das Recht sich als C++ Entwickler zu bezeichnen.
Und selbstverständlich gehört auch die Umkehrung dazu:
“Resource Release Is Destruction” - kurz RRID
.
Doch die erste Implementierung im GATE Projekt findet in C statt und hier fehlt dieses C++ Konzept wirklich sehr.
In C++ schreibt man sich einmal eine “Smart-Resource” Klasse …
1class MyResource 2{ 3private: 4 resource_type res; 5 6public: 7 MyResource() 8 { 9 this->res = create_my_resource(); 10 if(this->res == NULL) 11 { 12 throw std::runtime_error("Failed to create resouce"); 13 } 14 } 15 ~MyResource() 16 { 17 delete_my_resource(this->res); 18 } 19 20 resource_type get() 21 { 22 return this->res; 23 } 24};
… und diese bindet man dann im Programm ganz natürlich ein:
Der Programmablauf do_something()
sieht damit in C++ sehr sauber aus und
der Compiler garantiert die korrekte Freigabe aller Ressourcen.
Aber was tun wir jetzt in reinem C ?
Tja, hier wird oft alles in eine Funktion gepackt. Aber hier müssen wir uns um eine korrekte Ressourcenverwaltung selbst kümmern. Mein alter eingelernter Ansatz sieht dann so aus:
1int do_something() 2{ 3 int succeeded = 0; 4 resource_type res1 = NULL; 5 resource_type res2 = NULL; 6 resource_type res3 = NULL; 7 resource_type res4 = NULL; 8 9 do 10 { 11 res1 = create_my_resource(); 12 if(res1 == NULL) break; 13 res2 = create_my_resource(); 14 if(res2 == NULL) break; 15 res3 = create_my_resource(); 16 if(res3 == NULL) break; 17 res4 = create_my_resource(); 18 if(res4 == NULL) break; 19 20 ... 21 22 succeeded = 1; 23 } while(0); 24 25 if(res1 != NULL) delete_my_resource(res1); 26 if(res2 != NULL) delete_my_resource(res2); 27 if(res3 != NULL) delete_my_resource(res3); 28 if(res4 != NULL) delete_my_resource(res4); 29 30 return succeeded; 31}
Und jetzt stellen wir uns das Beispiel mit 4 mal so vielen Ressourcen vor …
Dann wird unser do_something()
schon ganz schön unübersichtlich. Auch die
Frage, an welcher Stelle man eine Funktion “abbrechen” darf, ist in C++
dank Exceptions leichter und schöner beschreibbar, als in C. Und zusätzlich
müssen wir uns den uninitialisierten Zustand auch noch irgendwie merken.
Fazit
Schätze deinen C++ Compiler!
Denn im Gegensatz zu uns Programmierern greift er das Thema Ressourcenverwaltung (meist) viel genauer und zuverlässiger auf.