Allocateurs
Les allocateurs sont utilisés par la bibliothèque C++ Standard pour gérer l’allocation et la désallocation des éléments stockés dans des conteneurs. Tous les conteneurs de bibliothèque C++ Standard, sauf std::array
avoir un paramètre de modèle de type allocator<Type>
, où Type
représente le type de l’élément conteneur. Par exemple, la vector
classe est déclarée comme suit :
template <
class Type,
class Allocator = allocator<Type>
>
class vector
La bibliothèque C++ Standard fournit une implémentation par défaut pour un allocateur. Dans C++11 et version supérieure, l’allocateur par défaut est mis à jour pour exposer une interface plus petite. Le nouvel allocateur est appelé allocateur minimal. En particulier, le membre construct()
de l'allocateur minimal prend en charge la sémantique de déplacement, ce qui peut améliorer considérablement les performances. Dans la plupart des cas, cet allocateur par défaut suffit. Dans C++11, tous les types et les fonctions de la bibliothèque STL qui acceptent un paramètre de type allocateur prennent en charge l'interface d'allocateur minimal, y compris std::function
, shared_ptr, allocate_shared()
et basic_string
. Pour plus d’informations sur l’allocateur par défaut, consultez allocator
Classe.
Écriture de votre propre allocateur (C++11)
L'allocateur par défaut utilise new
et delete
pour allouer et désallouer la mémoire. Si vous souhaitez utiliser une autre méthode d'allocation de la mémoire, telle que l'utilisation de la mémoire partagée, vous devez créer votre propre allocateur. Si vous ciblez C++11 et que vous devez écrire un nouvel allocateur personnalisé, faites-en un allocateur minimal si possible. Même si vous avez déjà implémenté un allocateur de style antérieur, changez-le en allocateur minimal pour tirer parti de la méthode construct()
la plus efficace fournie automatiquement.
Un allocateur minimal nécessite beaucoup moins de réutilisables et vous permet de vous concentrer sur les allocate
fonctions et deallocate
les fonctions membres, qui effectuent tout le travail. Lors de la création d'un allocateur minimal, n'implémentez aucun membre à l'exception de ceux indiqués dans l'exemple ci-dessous :
un constructeur de copie de conversion (voir l'exemple)
operator==
operator!=
allocate
deallocate
Le membre construct()
par défaut dans C++11 qui vous sera fourni effectue un transfert parfait et autorise la sémantique de déplacement. Dans de nombreux cas, il est beaucoup plus efficace que l'ancienne version.
Avertissement
Au moment de la compilation, la bibliothèque standard C++ utilise la allocator_traits
classe pour détecter les membres que vous avez explicitement fournis et fournit une implémentation par défaut pour tous les membres qui ne sont pas présents. N’interfèrez pas avec ce mécanisme en fournissant une spécialisation de allocator_traits
votre allocator !
L'exemple suivant montre une implémentation minimale d'un allocateur qui utilise malloc
et free
. Notez l'utilisation du nouveau type d'exception std::bad_array_new_length
qui est levé si la taille du tableau est inférieure à zéro ou supérieure à la taille maximale autorisée.
#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);
}
Écriture de votre propre allocateur (C++03)
Dans C++03, tout allocateur utilisé avec des conteneurs de bibliothèque C++ Standard doit implémenter les définitions de types suivantes :
const_pointer
const_reference
difference_type
pointer
rebind
reference
size_type
value_type
Par ailleurs, tout allocateur utilisé avec des conteneurs de bibliothèque C++ Standard doit implémenter les méthodes suivantes :
Constructeur
Constructeur de copie
Destructeur
address
allocate
construct
deallocate
destroy
max_size
operator!=
operator==
Pour plus d’informations sur ces définitions et méthodes de type, consultez allocator
Class.