util.smartptr.shared.const / 9 en C ++ 11:
Effets: construit un objet shared_ptr qui possède l'objet p et le deleter d. Les deuxième et quatrième constructeurs doivent utiliser une copie de a pour allouer de la mémoire à un usage interne.
Les deuxième et quatrième constructeurs ont ces prototypes:
template<class Y, class D, class A> shared_ptr(Y* p, D d, A a);
template<class D, class A> shared_ptr(nullptr_t p, D d, A a);
Dans la dernière version, util.smartptr.shared.const / 10 est équivalent à notre objectif:
Effets: construit un objet shared_ptr qui possède l'objet p et le deleter d. Lorsque T n'est pas un type de tableau, les premier et deuxième constructeurs activent shared_from_this avec p. Les deuxième et quatrième constructeurs doivent utiliser une copie de a pour allouer de la mémoire à un usage interne. Si une exception est levée, d (p) est appelé.
L'allocateur est donc utilisé s'il est nécessaire de l'allouer dans la mémoire allouée. Sur la base de la norme actuelle et des rapports de défauts pertinents, l'allocation n'est pas obligatoire mais assumée par le comité.
Bien que l'interface de shared_ptr
autorise une implémentation où il n'y a jamais de bloc de contrôle et tout shared_ptr
et weak_ptr
soit placé dans une liste chaînée, il n'y a pas une telle implémentation dans la pratique. De plus, le libellé a été modifié en supposant, par exemple, que le use_count
est partagé.
Le deleter est nécessaire pour déplacer uniquement constructible. Ainsi, il n'est pas possible d'avoir plusieurs exemplaires dans le shared_ptr
.
On peut imaginer une implémentation qui place le délétère dans un cadre spécialement conçu shared_ptr
et le déplace lorsqu'il shared_ptr
est supprimé. Bien que l'implémentation semble conforme, elle est également étrange, d'autant plus qu'un bloc de contrôle peut être nécessaire pour le compte d'utilisation (il est peut-être possible mais encore plus étrange de faire la même chose avec le compte d'utilisation).
DR pertinents que j'ai trouvés: 545 , 575 , 2434 (qui reconnaissent que toutes les implémentations utilisent un bloc de contrôle et semblent impliquer que les contraintes multithread le mandatent quelque peu), 2802 (qui exige que le suppresseur ne se déplace que constructible et empêche ainsi l'implémentation lorsque le deleter est copié entre plusieurs shared_ptr
).
a
) pour désallouer cette mémoire. Ce qui impliquerait un certain stockage de cette copie dea
. Il n'y a aucune information à ce sujet dans [util.smartptr.shared.dest].De std :: shared_ptr, nous avons:
Et de std :: allocate_shared nous obtenons:
Il semble donc que std :: allocate_shared devrait allouer le
deleter
avec votreAlloc
.EDIT: Et à partir du
n4810
§ 20.11.3.6 Création [util.smartptr.shared.create][Souligne tout le mien]
Donc, la norme dit que cela
std::allocate_shared
devrait être utiliséAlloc
pour le bloc de contrôle.la source
n4810
Réponse trouvée et mise à jour.make_shared
, pas des constructeurs eux-mêmes. Pourtant, je peux utiliser un membre pour les petits délétères.Je crois que cela n'est pas spécifié.
Voici la spécification des constructeurs concernés: [util.smartptr.shared.const] / 10
Maintenant, mon interprétation est que lorsque l'implémentation a besoin de mémoire pour un usage interne, elle le fait en utilisant
a
. Cela ne signifie pas que l'implémentation doit utiliser cette mémoire pour tout placer. Par exemple, supposons qu'il y ait cette implémentation étrange:Cette implémentation "utilise-t-elle une copie de
a
pour allouer de la mémoire à un usage interne"? Oui. Il n'alloue jamais de mémoire sauf en utilisanta
. Il y a beaucoup de problèmes avec cette implémentation naïve, mais disons qu'elle passe à l'utilisation d'allocateurs dans tous les cas sauf le plus simple dans lequel leshared_ptr
est construit directement à partir d'un pointeur et n'est jamais copié ou déplacé ou autrement référencé et il n'y a pas d'autres complications. Le fait est que ce n'est pas parce que nous n'imaginons pas qu'une implémentation valide prouve qu'elle ne peut théoriquement pas exister. Je ne dis pas qu'une telle implémentation se trouve réellement dans le monde réel, mais simplement que la norme ne semble pas l'interdire activement.la source
shared_ptr
pour les petits types alloue de la mémoire sur la pile. Et ne répond donc pas aux exigences standardstd::move(__d)
, et revenez àallocate
quand une copie est requise.