Allocators

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:

  1. ein konvertierender Kopierkonstruktor (siehe Beispiel)

  2. operator==

  3. operator!=

  4. allocate

  5. 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".

Siehe auch

C++-Standardbibliotheksreferenz