Condividi tramite


Allocatori

Gli allocatori vengono usati dalla libreria standard C++ per gestire l'allocazione e la deallocazione di elementi archiviati in contenitori. Tutti i contenitori della libreria standard C++ ad eccezione std::array di un parametro modello di tipo allocator<Type>, dove Type rappresenta il tipo dell'elemento contenitore. Ad esempio, la vector classe viene dichiarata come segue:

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

La libreria standard C++ offre un'implementazione predefinita per un allocatore. In C++11 e versioni successive, l'allocatore predefinito viene aggiornato in modo da esporre un'interfaccia più piccola. Il nuovo allocatore viene chiamato allocatore minimo. In particolare, il membro construct() dell'allocatore minimo supporta la semantica di spostamento, che consente di migliorare notevolmente le prestazioni. Nella maggior parte dei casi, l'allocatore predefinito dovrebbe essere sufficiente. In C++ 11 tutti i tipi e le funzioni della a libreria standard che accettano un parametro di tipo allocatore supportano l'iinterfaccia dell'allocatore minimo, tra cui std::function, shared_ptr, allocate_shared() e basic_string. Per altre informazioni sull'allocatore predefinito, vedere allocator Classe.

Scrittura di un codificatore personalizzato (C++11)

L'allocatore predefinito usa new e delete per allocare e deallocare la memoria. Se si vuole usare un altro metodo di allocazione della memoria, ad esempio l'uso di memoria condivisa, è necessario creare un allocatore personale. Se si usa C++ 11 ed è necessario scrivere un nuovo allocatore personalizzato, renderlo un allocatore minimo se possibile. Anche se è già stato implementato un allocatore obsoleto, provare a modificarlo in modo che diventi un allocatore minimo per sfruttare il più efficiente metodo construct() che verrà visualizzato automaticamente.

Un allocatore minimo richiede molto meno boilerplate e consente di concentrarsi sulle allocate funzioni membro e deallocate , che eseguono tutto il lavoro. Durante la creazione di un allocatore minimo, non implementare i membri tranne quelli illustrati nell'esempio riportato di seguito:

  1. un costruttore di copia di conversione (vedere l'esempio)

  2. operator==

  3. operator!=

  4. allocate

  5. deallocate

Il membro construct() predefinito di C++11 che verrà fornito eseguire l'inoltro perfetto e abilita la semantica di spostamento; in molti casi, è molto più efficiente rispetto alla versione precedente.

Avviso

In fase di compilazione, la libreria standard C++ usa la allocator_traits classe per rilevare i membri forniti in modo esplicito e fornisce un'implementazione predefinita per tutti i membri non presenti. Non interferire con questo meccanismo fornendo una specializzazione di allocator_traits per l'allocatore!

L'esempio seguente mostra un'implementazione minima di un allocatore che usa malloc e free. Si noti l'uso del nuovo tipo di eccezione std::bad_array_new_length che viene generato se la dimensione della matrice è minore di zero o maggiore della dimensione massima consentita.

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

Scrittura di un codificatore personalizzato (C++03)

In C++03 qualsiasi allocatore usato con i contenitori della libreria standard C++ deve implementare le definizioni dei tipi seguenti:

const_pointer
const_reference

difference_type
pointer

rebind
reference

size_type
value_type

Inoltre, qualsiasi allocatore usato con i contenitori della libreria standard C++ deve implementare i metodi seguenti:

Costruttore
Costruttore di copia
Distruttore

address
allocate
construct

deallocate
destroy
max_size

operator!=
operator==

Per altre informazioni su queste definizioni e metodi di tipo, vedere allocator Classe.

Vedi anche

Informazioni di riferimento per la libreria standard C++