Sorgfältiger Umgang mit Ressourcen

Inhaltsverzeichnis[Anzeigen]

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 mir 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 er Eindruck entsteht, explizite Speicherverwaltung ist notwendiges Wissen für einen C++-Entwickler.

Ressourcenmanagement

Automatische Speicherverwaltung

Log 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, das 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 Beispiel 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 angelegten 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 beliebten C++-Idiom an.

Explizite Speicherverwaltung

Mit der expliziten Speicherverwaltung betreten wir die Domäne der Experten. Dank der expliziten Spiecherverwaltung 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.

 

Tags: Speicher

Kommentare   

0 #1 home 2016-10-10 00:40
Wow, wonderful weblog structure! How long have you ever been blogging for?
you make running a blog look easy. The full glance of your web site is fantastic, as well as the content!
Zitieren

Kommentar schreiben


Modernes C++

Abonniere den Newsletter

Inklusive zwei Artikel meines Buchs
Introduction und Multithreading

Beiträge-Archiv

Sourcecode

Neuste Kommentare