Sdílet prostřednictvím


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::functionshared_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:

  1. převod konstruktoru kopírování (viz příklad)

  2. operator==

  3. operator!=

  4. allocate

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

Viz také

Standardní knihovna C++ – referenční dokumentace