Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
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:
konwertowanie konstruktora kopiowania (zobacz przykład)
operator==
operator!=
allocate
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.