Allokatoren
Allocators werden von der C++-Standardbibliothek zum Verarbeiten der Zuordnung und der Aufhebung der Zuordnung von Elementen verwendet, die in Containern gespeichert sind. Alle C++-Standardbibliothekscontainer mit Ausnahme std::array
eines Vorlagenparameters vom Typ allocator<Type>
, wobei Type
der Typ des Containerelements darstellt. Die Klasse wird beispielsweise vector
wie folgt deklariert:
template <
class Type,
class Allocator = allocator<Type>
>
class vector
Die C++-Standardbibliothek stellt eine Standardimplementierung für einen Allocator bereit. In C ++ Version 11 und höher wurde der Standardallocator aktualisiert, um eine kleinere Schnittstelle verfügbar zu machen. Die neue Zuweisung wird als minimaler Allocator bezeichnet. Insbesondere unterstützt das construct()
-Member des minimalen Allocators die Move-Semantik, wodurch die Leistung erheblich verbessert werden kann. In den meisten Fällen ist dieser Standardallocator ausreichend. In C ++ 11 unterstützen alle Standardbibliothekstypen und Funktionen, die einen Allocatortypparameter verwenden können, die Schnittstelle des minimalen Allocators, einschließlich std::function
, shared_ptr, allocate_shared()
und basic_string
. Weitere Informationen zum Standardzuordnungsmodul finden Sie unter allocator
"Klasse".
Schreiben von eigenen Allocators (C ++ 11)
Der Standardallocator verwendet new
und delete
zum Zuordnen von Speichern und zum Aufheben der Zuordnung. Wenn Sie eine andere Methode für die Speicherzuordnung verwenden möchten, z. B. die Verwendung von gemeinsam genutztem Speicher, müssen Sie einen eigenen Allocator erstellen. Wenn Sie C ++ 11 als Ziel verwenden und Sie einen neuen benutzerdefinierten Allocator schreiben müssen, erstellen Sie möglichst einen minimalen Allocator. Auch wenn Sie bereits einen herkömmlichen Allocator implementiert haben, ziehen Sie in Betracht, ihn in einen minimalen Allocator zu ändern, um die effizientere Methode construct()
nutzen zu können, die Ihnen automatisch bereitgestellt wird.
Ein minimaler Allokator erfordert viel weniger Bausteine und ermöglicht es Ihnen, sich auf die allocate
Funktionen und deallocate
Member zu konzentrieren, die alle Arbeiten ausführen. Implementieren Sie beim Erstellen eines minimalen Allocators keine Member außer den im folgenden Beispiel dargestellten:
ein konvertierender Kopierkonstruktor (siehe Beispiel)
operator==
operator!=
allocate
deallocate
Der C ++ 11-Standardmember construct()
, der Ihnen bereitgestellt wird, optimiert die Weiterleitung und aktiviert die move-Semantik. Diese Version ist in den meisten Fällen wesentlich effizienter als die ältere Version.
Warnung
Zur Kompilierungszeit verwendet die C++-Standardbibliothek die allocator_traits
Klasse, um zu ermitteln, welche Member Sie explizit angegeben haben, und stellt eine Standardimplementierung für alle Elemente bereit, die nicht vorhanden sind. Stören Sie diesen Mechanismus nicht, indem Sie eine Spezialisierung allocator_traits
für Ihren Allokator bereitstellen!
Das folgende Beispiel zeigt eine minimale Implementierung eines Allocators, der malloc
und free
verwendet. Beachten Sie die Verwendung des neuen Ausnahmetyps std::bad_array_new_length
. Diese Ausnahme wird ausgelöst, wenn die Arraygröße kleiner als 0 (null) oder größer als die maximal zulässige Größe ist.
#pragma once
#include <stdlib.h> //size_t, malloc, free
#include <new> // bad_alloc, bad_array_new_length
#include <memory>
template <class T>
struct Mallocator
{
typedef T value_type;
Mallocator() noexcept {} //default ctor not required by C++ Standard Library
// A converting copy constructor:
template<class U> Mallocator(const Mallocator<U>&) noexcept {}
template<class U> bool operator==(const Mallocator<U>&) const noexcept
{
return true;
}
template<class U> bool operator!=(const Mallocator<U>&) const noexcept
{
return false;
}
T* allocate(const size_t n) const;
void deallocate(T* const p, size_t) const noexcept;
};
template <class T>
T* Mallocator<T>::allocate(const size_t n) const
{
if (n == 0)
{
return nullptr;
}
if (n > static_cast<size_t>(-1) / sizeof(T))
{
throw std::bad_array_new_length();
}
void* const pv = malloc(n * sizeof(T));
if (!pv) { throw std::bad_alloc(); }
return static_cast<T*>(pv);
}
template<class T>
void Mallocator<T>::deallocate(T * const p, size_t) const noexcept
{
free(p);
}
Schreiben von eigenen Allocators (C ++ 03)
In C ++03 muss jeder Allocator, der mit C++-Standardbibliohekcontainern verwendet wird, die folgenden Typdefinitionen implementieren:
const_pointer
const_reference
difference_type
pointer
rebind
reference
size_type
value_type
Außerdem muss jeder Allocator, der mit C++-Standardbibliohekcontainern verwendet wird, die folgenden Methoden implementieren:
Konstruktor
Kopierkonstruktor
Destruktor
address
allocate
construct
deallocate
destroy
max_size
operator!=
operator==
Weitere Informationen zu diesen Typdefinitionen und -methoden finden Sie unter allocator
"Class".