Alokátory
Alokátory jsou používány standardní knihovnou jazyka C++ ke zpracování přidělení a uvolnění prvků uložených v kontejnerech. Všechny kontejnery standardní knihovny C++ s výjimkou std::array
parametru šablony typu allocator<Type>
, kde Type
představuje typ elementu kontejneru. vector
Například třída je deklarována takto:
template <
class Type,
class Allocator = allocator<Type>
>
class vector
Standardní knihovna jazyka C++ poskytuje výchozí implementaci pro alokátor. V jazyce C++11 a novějším se výchozí alokátor aktualizuje tak, aby zpřístupnil menší rozhraní; nový alokátor se nazývá minimální alokátor. Zejména minimální člen alokátoru construct()
podporuje sémantiku pohybu, což může výrazně zlepšit výkon. Ve většině případů by měl být tento výchozí alokátor dostatečný. V jazyce C++11 podporují všechny typy a funkce standardní knihovny, které přebírají parametr typu alokátoru minimální rozhraní alokátoru, včetně std::function
shared_ptr, allocate_shared()
, a basic_string
. Další informace o výchozím alokátoru najdete v tématu allocator
Třída.
Psaní vlastního alokátoru (C++11)
Výchozí alokátor používá new
a delete
přiděluje a uvolní paměť. Pokud chcete použít jinou metodu přidělování paměti, například použití sdílené paměti, musíte vytvořit vlastní alokátor. Pokud cílíte na C++11 a potřebujete napsat nový vlastní alokátor, pokud je to možné, udělejte z něj minimální alokátor. I když jste již implementovali alokátor starého stylu, zvažte jeho úpravu tak, aby byl minimální alokátor , aby využil výhod efektivnější construct()
metody, která bude poskytována automaticky.
Minimální alokátor vyžaduje mnohem méně často používaný a umožňuje soustředit se na allocate
členské deallocate
funkce, které dělají všechny práce. Při vytváření minimálního alokátoru neimplementujte žádné členy s výjimkou členů zobrazených v následujícím příkladu:
převod konstruktoru kopírování (viz příklad)
operator==
operator!=
allocate
deallocate
Výchozí construct()
člen C++11, který vám poskytne perfektní předávání a umožňuje sémantiku přesunutí, je mnohem efektivnější v mnoha případech než starší verze.
Upozorňující
V době kompilace používá allocator_traits
standardní knihovna jazyka C++ třídu ke zjištění, které členy jste explicitně zadali, a poskytuje výchozí implementaci pro všechny členy, které nejsou přítomny. Nezasahujte do tohoto mechanismu tím, že poskytnete specializaci allocator_traits
pro vašeho alokátora!
Následující příklad ukazuje minimální implementaci alokátoru, který používá malloc
a free
. Všimněte si použití nového typu std::bad_array_new_length
výjimky, který je vyvolán, pokud je velikost pole menší než nula nebo větší než maximální povolená velikost.
#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);
}
Psaní vlastního alokátoru (C++03)
V jazyce C++03 musí každý alokátor použitý s kontejnery standardní knihovny C++ implementovat následující definice typu:
const_pointer
const_reference
difference_type
pointer
rebind
reference
size_type
value_type
Kromě toho musí všechny alokátory používané s kontejnery standardní knihovny C++ implementovat následující metody:
Konstruktor
Kopírovací konstruktor
Destruktor
address
allocate
construct
deallocate
destroy
max_size
operator!=
operator==
Další informace o těchto definicích typů a metodách naleznete v tématu allocator
Třída.