Die Bibliothek Boost.PointerContainer bietet für die Verwaltung dynamisch reservierter Objekte spezielle Container an. Verwenden Sie C++11, können Sie einen entsprechenden Container zum Beispiel mit std::vector<std::unique_ptr<int>>
selbst erstellen. Die von Boost.PointerContainer angebotenen Container können jedoch zusätzlichen Komfort bieten.
boost::ptr_vector
in Aktion#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>
int main()
{
boost::ptr_vector<int> v;
v.push_back(new int{1});
v.push_back(new int{2});
std::cout << v.back() << '\n';
}
Die Klasse boost::ptr_vector
, die im Beispiel 2.1 verwendet wird und in der Headerdatei boost/ptr_container/ptr_vector.hpp
definiert ist, funktioniert grundsätzlich genauso wie ein Container vom Typ std::vector<std::unique_ptr<int>>
. Da boost::ptr_vector
jedoch weiß, dass es dynamisch reservierte Objekte speichert, geben Methoden wie back()
eine Referenz auf ein dynamisch reserviertes Objekt zurück und keinen Zeiger. Das Beispiel gibt entsprechend 2
auf die Standardausgabe aus.
boost::ptr_set
mit intuitiv richtiger Sortierung#include <boost/ptr_container/ptr_set.hpp>
#include <boost/ptr_container/indirect_fun.hpp>
#include <set>
#include <memory>
#include <functional>
#include <iostream>
int main()
{
boost::ptr_set<int> s;
s.insert(new int{2});
s.insert(new int{1});
std::cout << *s.begin() << '\n';
std::set<std::unique_ptr<int>, boost::indirect_fun<std::less<int>>> v;
v.insert(std::unique_ptr<int>(new int{2}));
v.insert(std::unique_ptr<int>(new int{1}));
std::cout << **v.begin() << '\n';
}
Beispiel 2.2 zeigt einen anderen Grund, warum es von Vorteil sein kann, einen spezialisierten Container zu verwenden. In diesem Beispiel werden dynamisch reservierte Variablen vom Typ int
in einem boost::ptr_set
und in einem std::set
gespeichert. Für das std::set
wird auf std::unique_ptr
zugegriffen.
boost::ptr_set
versteht automatisch, dass die Reihenfolge der Elemente von den gespeicherten int
-Werten abhängt. std::set
hingegen würde std::unique_ptr
miteinander vergleichen – also Smartpointer und nicht die Variablen, auf die die Smartpointer zeigen. Damit die Sortierung im Beispiel 2.2 auch bei std::set
auf den int
-Werten basiert, muss angegeben werden, wie Vergleiche durchzuführen sind. Hierzu wird auf eine Klasse boost::indirect_fun
zugegriffen, die aus Boost.PointerContainer stammt. Mit Hilfe dieser Klasse wird std::set
mitgeteilt, dass die Sortierung nicht basierend auf den Smartpointern durchgeführt werden soll, sondern basierend auf den int
-Variablen, auf die die Smartpointer zeigen. Wenn Sie das Beispiel ausführen, wird zweimal 1
ausgegeben.
Neben boost::ptr_vector
und boost::ptr_set
stehen weitere Container zur Verfügung, die auf die Verwaltung dynamisch reservierter Objekte spezialisiert sind. Dazu gehören boost::ptr_deque
, boost::ptr_list
, boost::ptr_map
, boost::ptr_unordered_set
und boost::ptr_unordered_map
. Diese Container entsprechen den aus der Standardbibliothek bekannten Containern.
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/ptr_container/ptr_inserter.hpp>
#include <array>
#include <algorithm>
#include <iostream>
int main()
{
boost::ptr_vector<int> v;
std::array<int, 3> a{{0, 1, 2}};
std::copy(a.begin(), a.end(), boost::ptr_container::ptr_back_inserter(v));
std::cout << v.size() << '\n';
}
Boost.PointerContainer bietet für seine Container Inserter an. Diese befinden sich im Namensraum boost::ptr_container
und sind in der Headerdatei boost/ptr_container/ptr_inserter.hpp
definiert.
Im Beispiel 2.3 wird auf die Funktion boost::ptr_container::ptr_back_inserter()
zugegriffen, die einen Inserter vom Typ boost::ptr_container::ptr_back_insert_iterator
erstellt. Dieser wird an std::copy()
übergeben, um die Zahlen im Array a in den Vektor v zu kopieren. Da v ein Container vom Typ boost::ptr_vector
ist, der Adressen von dynamisch reservierten int
-Objekten erwartet, muss ein von Boost.PointerContainer angebotener Inserter verwendet werden. Diese erstellen eine Kopie mit new
auf dem Heap und fügen die Adresse dem Container hinzu.
Neben boost::ptr_container::ptr_back_inserter()
bietet Boost.PointerContainer die Funktionen boost::ptr_container::ptr_front_inserter()
und boost::ptr_container::ptr_inserter()
, um entsprechende Inserter zu erstellen.
Entwickeln Sie ein Programm, in dem mehrere Instanzen einer Klasse animal
mit den Eigenschaften name, legs und has_tail erstellt und in einem Container von Boost.PointerContainer gespeichert werden. Sortieren Sie den Container aufsteigend nach der Anzahl der Beine und schreiben Sie alle Elemente im Container in die Standardausgabe.