Namespaces
Variants

std:: allocate_shared, std:: allocate_shared_for_overwrite

From cppreference.net
Memory management library
( exposition only* )
Allocators
Uninitialized memory algorithms
Constrained uninitialized memory algorithms
Memory resources
Uninitialized storage (until C++20)
( until C++20* )
( until C++20* )
( until C++20* )

Garbage collector support (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
(C++11) (until C++23)
Défini dans l'en-tête <memory>
template < class T, class Alloc, class ... Args >
shared_ptr < T > allocate_shared ( const Alloc & alloc, Args && ... args ) ;
(1) (depuis C++11)
template < class T, class Alloc >
shared_ptr < T > allocate_shared ( const Alloc & alloc, std:: size_t N ) ;
(2) (depuis C++20)
template < class T, class Alloc >
shared_ptr < T > allocate_shared ( const Alloc & alloc ) ;
(3) (depuis C++20)
template < class T, class Alloc >

shared_ptr < T > allocate_shared ( const Alloc & alloc, std:: size_t N,

const std:: remove_extent_t < T > & u ) ;
(4) (depuis C++20)
template < class T, class Alloc >

shared_ptr < T > allocate_shared ( const Alloc & alloc,

const std:: remove_extent_t < T > & u ) ;
(5) (depuis C++20)
template < class T, class Alloc >
shared_ptr < T > allocate_shared_for_overwrite ( const Alloc & alloc ) ;
(6) (depuis C++20)
template < class T, class Alloc >

shared_ptr < T > allocate_shared_for_overwrite ( const Alloc & alloc,

std:: size_t N ) ;
(7) (depuis C++20)

Alloue de la mémoire pour un objet en utilisant une copie de alloc (relié pour un value_type non spécifié) et initialise l'objet avec les arguments fournis. Retourne un objet std::shared_ptr gérant l'objet nouvellement créé.

1) L'objet est de type T , et est construit comme par std:: allocator_traits < Alloc > :: construct
( a, pt, ( std:: forward < Args > ( args ) ... )
, où pt est un std:: remove_cv_t < T > * pointeur vers un espace de stockage adapté pour contenir un objet de type std:: remove_cv_t < T > . Si l'objet doit être détruit, il est détruit comme par std:: allocator_traits < Alloc > :: destroy ( a, pt ) , où pt est un pointeur vers cet objet de type std:: remove_cv_t < T > .
Dans la description ci-dessus, a est de type Alloc , et c'est une copie potentiellement re-liée de alloc .

Cette surcharge participe à la résolution de surcharge seulement si T n'est pas un type tableau.

(depuis C++20)
2) L'objet est de type std:: remove_extent_t < T > [ N ] . Chaque élément possède une valeur initiale par défaut.
Cette surcharge participe à la résolution de surcharge uniquement si T est un type de tableau non borné.
3) L'objet est de type T . Chaque élément a une valeur initiale par défaut.
Cette surcharge participe à la résolution de surcharge uniquement si T est un type tableau borné.
4) L'objet est de type std:: remove_extent_t < T > [ N ] . Chaque élément a la valeur initiale u .
Cette surcharge participe à la résolution de surcharge uniquement si T est un type de tableau non borné.
5) L'objet est de type T . Chaque élément a la valeur initiale u .
Cette surcharge participe à la résolution de surcharge uniquement si T est un type de tableau borné.
6) L'objet est de type T .
  • Si T n'est pas un type tableau, l'objet est construit comme par :: new ( pv ) T , où pv est un pointeur void * vers un espace de stockage adapté pour contenir un objet de type T . Si l'objet doit être détruit, il est détruit comme par pt - > ~T ( ) , où pt est un pointeur vers cet objet de type T .
  • Si T est un type tableau à taille fixe, la valeur initiale est non spécifiée pour chaque élément.
Cette surcharge participe à la résolution de surcharge seulement si T n'est pas un type tableau ou est un type tableau à taille fixe.
7) L'objet est de type std:: remove_extent_t < T > [ N ] . La valeur initiale n'est pas spécifiée pour chaque élément.
Cette surcharge participe à la résolution de surcharge uniquement si T est un type de tableau non borné.

Table des matières

Initialisation et destruction des éléments du tableau

Dans la description ci-dessous, a est de type Alloc , et c'est une copie potentiellement re-liée de alloc .

Les éléments du tableau de type U sont initialisés dans l'ordre croissant de leurs adresses.

  • Si U n'est pas un type tableau, chaque élément est construit comme par l'expression suivante, où pu est un pointeur std:: remove_cv_t < U > * vers un stockage adapté pour contenir un objet de type std:: remove_cv_t < U > , et pv est un pointeur void * vers un stockage adapté pour contenir un objet de type U :
2,3) std:: allocator_traits < Alloc > :: construct ( a, pu )
4,5) std:: allocator_traits < Alloc > :: construct ( a, pu, u )
6,7) :: new ( pv ) U
  • Sinon, initialise récursivement les éléments de chaque élément. Pour la dimension suivante :

Lorsque la durée de vie de l'objet géré par le std::shared_ptr retourné se termine, ou lorsque l'initialisation d'un élément du tableau lève une exception, les éléments initialisés sont détruits dans l'ordre inverse de leur construction initiale.

Pour chaque élément du tableau de type non-tableau U à détruire, il est détruit comme par l'expression suivante :

2-5) std:: allocator_traits < Alloc > :: destroy ( a, pu ) , où pu est un pointeur U * vers cet élément du tableau de type U
6,7) pu - > ~U ( ) , où pu est un pointeur vers cet élément du tableau de type U
(depuis C++20)

Paramètres

alloc - l' Allocator à utiliser
args... - liste d'arguments avec lesquels une instance de T sera construite
N - taille du tableau à utiliser
u - la valeur initiale pour initialiser chaque élément du tableau

Valeur de retour

std::shared_ptr vers un objet de type T ou std:: remove_extent_t < T > [ N ] si T est un type de tableau non borné (depuis C++20) .

Pour le std::shared_ptr r retourné, r. get ( ) renvoie un pointeur non nul et r. use_count ( ) renvoie 1 .

Exceptions

Peut lever les exceptions levées par Alloc :: allocate ( ) ou par le constructeur de T . Si une exception est levée, (1) n'a aucun effet. Si une exception est levée durant la construction du tableau, les éléments déjà initialisés sont détruits dans l'ordre inverse (depuis C++20) .

Notes

Ces fonctions allouent généralement plus de mémoire que sizeof ( T ) pour permettre des structures de gestion internes telles que les compteurs de référence.

Comme std::make_shared , cette fonction effectue généralement une seule allocation et place à la fois l'objet T et le bloc de contrôle dans le bloc de mémoire alloué (la norme recommande mais n'exige pas cela, toutes les implémentations connues le font). Une copie de alloc est stockée dans le bloc de contrôle afin de pouvoir être utilisée pour le désallouer une fois que les compteurs de références partagées et faibles atteignent zéro.

Contrairement aux std::shared_ptr constructors , std::allocate_shared n'accepte pas de suppresseur personnalisé séparé : l'allocateur fourni est utilisé pour la destruction du bloc de contrôle et de l'objet T , ainsi que pour la désallocation de leur bloc de mémoire partagé.

std::shared_ptr prend en charge les types tableau (depuis C++17), mais std::allocate_shared ne le fait pas. Cette fonctionnalité est prise en charge par boost::allocate_shared .

(jusqu'à C++20)

Un constructeur active shared_from_this avec un pointeur ptr de type U* signifie qu'il détermine si U possède une classe de base non ambiguë et accessible (depuis C++17) qui est une spécialisation de std::enable_shared_from_this , et si c'est le cas, le constructeur évalue if ( ptr ! = nullptr && ptr - > weak_this  . expired ( ) )
ptr - > weak_this = std:: shared_ptr < std:: remove_cv_t < U >>
( * this, const_cast < std:: remove_cv_t < U > * > ( ptr ) ) ;
.

L'assignation à weak_this n'est pas atomique et entre en conflit avec tout accès potentiellement concurrent au même objet. Cela garantit que les appels futurs à shared_from_this() partageront la propriété avec le std::shared_ptr créé par ce constructeur de pointeur brut.

Le test ptr - > weak_this  . expired ( ) dans le code ci-dessus garantit que weak_this n'est pas réaffecté s'il indique déjà un propriétaire. Ce test est requis à partir de C++17.

Macro de test de fonctionnalité Valeur Std Fonctionnalité
__cpp_lib_smart_ptr_for_overwrite 202002L (C++20) Création de pointeurs intelligents avec initialisation par défaut ( std::allocate_shared_for_overwrite , std::make_shared_for_overwrite , std::make_unique_for_overwrite ) ; surcharges ( 6,7 )

Exemple

#include <cstddef>
#include <iostream>
#include <memory>
#include <memory_resource>
#include <vector>
class Value
{
    int i;
public:
    Value(int i) : i(i) { std::cout << "Value(), i = " << i << '\n'; }
    ~Value() { std::cout << "~Value(), i = " << i << '\n'; }
    void print() const { std::cout << "i = " << i << '\n'; }
};
int main()
{
    // Créer un allocateur polymorphe utilisant la ressource de tampon monotone
    std::byte buffer[sizeof(Value) * 8];
    std::pmr::monotonic_buffer_resource resource(buffer, sizeof(buffer));
    std::pmr::polymorphic_allocator<Value> allocator(&resource);
    std::vector<std::shared_ptr<Value>> v;
    for (int i{}; i != 4; ++i)
        // Utiliser std::allocate_shared avec l'allocateur personnalisé
        v.emplace_back(std::allocate_shared<Value>(allocator, i));
    for (const auto& sp : v)
        sp->print();
} //< Tous les shared_ptr nettoieront automatiquement lorsqu'ils sortiront de la portée.

Sortie :

Value(), i = 0
Value(), i = 1
Value(), i = 2
Value(), i = 3
i = 0
i = 1
i = 2
i = 3
~Value(), i = 0
~Value(), i = 1
~Value(), i = 2
~Value(), i = 3

Rapports de défauts

Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.

DR Appliqué à Comportement publié Comportement corrigé
LWG 3216 C++20 std::allocate_shared a toujours re-lié l'allocateur
avant de construire et détruire les objets
le re-liage est optionnel
LWG 4024 C++20 il n'était pas clair comment les objets construits dans
std::allocate_shared_for_overwrite sont détruits
clarifié

Voir aussi

construit un nouveau shared_ptr
(fonction membre publique)
crée un pointeur partagé qui gère un nouvel objet
(fonction template)