Sorgfältiger Umgang mit Ressourcen

Der sorgfältige Umgang mit Ressourcen, sei es Speicher, Dateien oder Sockets, ist zentral für die Programmierung in C++. Das gilt insbesondere für die embedded Programmierung, da sich diese gerne durch eingeschränkte Ressourcen auszeichnet. Daher will ich mich diesem vielschichtigen und anspruchsvollen Thema in mehreren Artikeln widmen.

 

In meiner ersten Naivität wollte ich in diesem Artikel sofort mit der Speicherallokation mit den Operator new loslegen. Gott sei Dank habe ich mich eines besseren besonnen. Speicherallokation ist nur ein, wenn auch ein wichtiger Aspekt von Ressourcenmanagement in C++. Die Geschichte ist aber deutlich vielseitiger. Daher werde ich einen Schritt zurücktreten und mich drei Bereichen von Ressourcenmanagement in C++ widmen.

Da gibt es die automatische Speicherverwaltung in C++, in der der Anwender die Mechanismen von C++ relativ naiv nutzen kann, da kommen die bekannten C++-Idiome zum Einsatz, auf denen zum Teil die automatische Speicherverwaltung basiert und letztendlich gibt es noch die explizite Speicherverwaltung, in der der Entwickler als Experte die Speicherverwaltung in die eigene Hand nimmt. Genau dieser Abstufung von der einfachen Anwendung zur Expertendomäne werde ich in meiner Gliederung folgen. Denn, was ich nicht will, ist, dass der Eindruck entsteht, explizite Speicherverwaltung ist notwendiges Wissen für einen C++-Entwickler.

Ressourcenmanagement

Automatische Speicherverwaltung

Los geht es auf der elementarsten Ebene mit den Smart Pointern.

Smart Pointer

C++ bietet vier verschiedene Smart Pointer an. Jeder besitzt die Aufgabe, den Lebenszyklus seiner zugrundeliegenden Ressource automatisch zu verwalten. Während der std::unique_ptr den Lebenszyklus genau einer Ressource verwaltet, teilt sich der std::shared_ptr seine Ressource mit einem anderen std::shared_ptr. Dabei können beim std::shared_ptr Zyklen auftreten, so dass der Speicher nicht automatisch freigegeben werden kann. Diese Zyklen zu brechen ist genau die Aufgabe von std::weak_ptr. Der Vierte im Bunde ist der std::auto_ptr. std::auto_ptr ist mit C++11 deprecated. Warum? Das werde ich in einem späteren Artikel klären. 

STL-Container

STL-Container cont wie std::vector oder auch std::string verwalten automatisch ihren Speicher. So besitzen sie zum Beispiel eine Methode cont.push_back, um ein neues Element an den Container anzuhängen. Dabei wird automatisch die Größe des Containers angepasst. Es geht auch anders herum. Mit der Methode cont.shrink_to_fit wird ihre Größe auf ihren tatsächlichen Inhalt reduziert.

C++-Idiome

Jede moderne STL-Implementierung verwendet die drei C++-Idiome Move-Semantik, Perfekt-Forwarding und das RAII-Idiom exzessiv. Um die Mechanismen darunter zu verstehen, bewegen wir uns aber schon auf anspruchsvollerem Terrain als bei der automatischen Speicherverwaltung. Bevor ich auf die Details eingehe, zuerst ein kleiner Appetitanreger.

Move-Semantik

Die zentrale Idee der Move-Semantik ist es, dass es besser ist, große Objekte billig zu verschieben statt teuer zu kopieren. Das trifft umso mehr zu, da es Objekte gibt, die gar nicht kopiert werden können. Ein typisches Beispiel ist ein Mutex oder kürzlich vorgestellte Smart Pointer std::unique_ptr.

Perfekt-Forwarding

Perfekt-Forwarding verwendet unter der Decke ähnliche Mechanismen wie die Move-Semantik. Die zentrale Idee von Perfekt-Forwarding ist aber eine andere. Bei Perfekt-Forwarding geht es darum, Objekte in einem Funktions-Template anzunehmen und sie mit ihren identischen Eigenschaften weiterzureichen. Typische Beispiele sind Konstruktoren, die ihre Argumente annehmen und an einen Basisklassenkonstruktor weiterreichen oder auch Fabrikfunktionen, die als Ergebnis ein neu erzeugtes Objekt zurückgeben. 

RAII-Idiom

Das Prinzip des RAII-Idiom ist sehr einfach. Bei ihr wird die Ressourcenbelegung und -freigabe an den Lebenszyklus eines auf dem Stack angelegtem Objekts gebunden. So wird im Konstruktor des Objekts die Ressource initialisiert und im Destruktor wieder freigegeben. Damit verwaltet die C++-Laufzeit automatisch den Lebenszyklus des Objekts und somit der Ressource. Das Akronym RAII steht für Resource Acquisition Is Initialization. Smart Pointer wenden dieses beliebte C++-Idiom an.

Explizite Speicherverwaltung

Mit der expliziten Speicherverwaltung betreten wir die Domäne der Experten. Dank der expliziten Speicherverwaltung ist es möglich, auf Klassenebene oder auch global die Speicherverwaltung- und freigabe für Objekt oder Arrays von Objekten in die Hand zu nehmen. Selbst eigene Speicherallokatoren lassen sich mit Hilfe von placement new verwenden und die Objekte in speziellen Speicherbereichen erzeugen.

Wie geht's weiter?

Wie versprochen, arbeite ich mit von unten nach oben durch die verschiedenen Ebenen im Umgang mit Ressourcen. Los geht es im nächsten Artikel mit der automatischen Speicherverwaltung mit Smart Pointern.

 

 

 

 

 

 

 

 

title page smalltitle page small Go to Leanpub/cpplibrary "What every professional C++ programmer should know about the C++ standard library".   Hole dir dein E-Book. Unterstütze meinen Blog.

 

Mentoring

Stay Informed about my Mentoring

 

Rezensionen

Tutorial

Besucher

Heute 474

Gestern 1497

Woche 8017

Monat 32876

Insgesamt 3331788

Aktuell sind 61 Gäste und keine Mitglieder online

Kubik-Rubik Joomla! Extensions

Abonniere den Newsletter (+ pdf Päckchen)

Beiträge-Archiv

Sourcecode

Neuste Kommentare