Alokatory

Alokatory są używane przez bibliotekę standardową języka C++ do obsługi alokacji i cofania przydziału elementów przechowywanych w kontenerach. Wszystkie kontenery biblioteki standardowej C++ z wyjątkiem std::array parametru szablonu typu allocator<Type>, gdzie Type reprezentuje typ elementu kontenera. Na przykład vector klasa jest zadeklarowana w następujący sposób:

template <
    class Type,
    class Allocator = allocator<Type>
>
class vector

Biblioteka Standardowa języka C++ udostępnia domyślną implementację alokatora. W języku C++11 lub nowszym domyślny alokator jest aktualizowany w celu uwidocznienia mniejszego interfejsu; nowy alokator jest nazywany minimalnym alokatorem. W szczególności element członkowski minimalnego alokatora construct() obsługuje semantykę przenoszenia, co może znacznie poprawić wydajność. W większości przypadków ten domyślny alokator powinien być wystarczający. W języku C++11 wszystkie typy i funkcje biblioteki standardowej, które przyjmują parametr typu alokatora, obsługują minimalny interfejs alokatora, w tym std::function, shared_ptr, allocate_shared()i basic_string. Aby uzyskać więcej informacji na temat domyślnego alokatora, zobacz allocator Klasa.

Pisanie własnego alokatora (C++11)

Domyślny alokator używa funkcji new i delete do przydzielania i cofania przydziału pamięci. Jeśli chcesz użyć innej metody alokacji pamięci, takiej jak użycie pamięci udostępnionej, musisz utworzyć własny alokator. Jeśli używasz języka C++11 i musisz napisać nowy alokator niestandardowy, jeśli jest to możliwe, dokonaj minimalnej alokacji. Nawet jeśli zaimplementowano już alokator starego stylu, rozważ zmodyfikowanie go jako minimalnej alokatora w celu skorzystania z bardziej wydajnej construct() metody, która zostanie udostępniona automatycznie.

Minimalny alokator wymaga znacznie mniej standardowy i umożliwia skupienie się na allocate funkcjach składowych i deallocate , które wykonują całą pracę. Podczas tworzenia minimalnej alokatora nie implementuj żadnych elementów członkowskich, z wyjątkiem elementów przedstawionych w poniższym przykładzie:

  1. konwertowanie konstruktora kopiowania (zobacz przykład)

  2. operator==

  3. operator!=

  4. allocate

  5. deallocate

Domyślny construct() element członkowski języka C++11, który zostanie udostępniony w celu zapewnienia doskonałego przekazywania i umożliwia semantyka przenoszenia; jest znacznie bardziej wydajny w wielu przypadkach niż starsza wersja.

Ostrzeżenie

W czasie kompilacji biblioteka standardowa języka C++ używa allocator_traits klasy do wykrywania, które elementy członkowskie zostały jawnie podane i zapewnia domyślną implementację dla wszystkich elementów członkowskich, które nie są obecne. Nie ingeruj w ten mechanizm, zapewniając specjalizację allocator_traits dla alokatora!

W poniższym przykładzie pokazano minimalną implementację alokatora używającego elementów malloc i free. Zwróć uwagę na użycie nowego typu std::bad_array_new_length wyjątku, który jest zgłaszany, jeśli rozmiar tablicy jest mniejszy niż zero lub większy niż maksymalny dozwolony rozmiar.

#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);
}

Pisanie własnego alokatora (C++03)

W języku C++03 każdy alokator używany z kontenerami biblioteki standardowej języka C++ musi implementować następujące definicje typów:

const_pointer
const_reference

difference_type
pointer

rebind
reference

size_type
value_type

Ponadto każdy alokator używany z kontenerami biblioteki standardowej języka C++ musi implementować następujące metody:

Konstruktor
Konstruktor kopiujący
Destruktor

address
allocate
construct

deallocate
destroy
max_size

operator!=
operator==

Aby uzyskać więcej informacji na temat tych definicji typów i metod, zobacz allocator Klasa.

Zobacz też

Dokumentacja standardowej biblioteki C++