util.smartptr.shared.const / 9 em C ++ 11:
Efeitos: constrói um objeto shared_ptr que possui o objeto pe deleter d. O segundo e o quarto construtores devem usar uma cópia de a para alocar memória para uso interno.
O segundo e o quarto construtores têm estes protótipos:
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);
No rascunho mais recente, util.smartptr.shared.const / 10 é equivalente para nosso propósito:
Efeitos: constrói um objeto shared_ptr que possui o objeto pe deleter d. Quando T não é um tipo de matriz, o primeiro e o segundo construtores ativam shared_from_this com p. O segundo e o quarto construtores devem usar uma cópia de a para alocar memória para uso interno. Se uma exceção for lançada, d (p) será chamado.
Portanto, o alocador é usado se houver necessidade de alocá-lo na memória alocada. Com base no padrão atual e nos relatórios de defeitos relevantes, a alocação não é obrigatória, mas assumida pelo comitê.
Embora a interface de shared_ptr
permita uma implementação em que nunca haja um bloco de controle e tudo shared_ptr
e weak_ptr
seja colocada em uma lista vinculada, não existe tal implementação na prática. Além disso, o texto foi modificado assumindo, por exemplo, que ele use_count
é compartilhado.
O deleter é necessário para mover apenas construtível. Portanto, não é possível ter várias cópias no shared_ptr
.
Pode-se imaginar uma implementação que coloque o deleter em um projeto especialmente projetado shared_ptr
e o mova quando o especial shared_ptr
for excluído. Embora a implementação pareça estar em conformidade, também é estranha, especialmente porque um bloco de controle pode ser necessário para a contagem de uso (talvez seja possível, mas ainda mais estranho, fazer a mesma coisa com a contagem de uso).
DRs relevantes que encontrei: 545 , 575 , 2434 (que reconhecem que todas as implementações estão usando um bloco de controle e parecem implicar que restrições de multi-threading o exigem de alguma forma), 2802 (que exige que o deleter se mova apenas construtível e, portanto, impeça a implementação onde o deleter é copiado entre vários shared_ptr
).
a
) para desalocar essa memória. O que implicaria algum armazenamento dessa cópia dea
. Não há informações sobre isso em [util.smartptr.shared.dest].De std :: shared_ptr , temos:
E de std :: assignate_shared , obtemos:
Portanto, parece que std :: assignate_shared deve alocar o
deleter
com o seuAlloc
.EDIT: E a partir de
n4810
§20.11.3.6 Criação [util.smartptr.shared.create][Ênfase toda minha]
Portanto, o padrão está dizendo que
std::allocate_shared
deve ser usadoAlloc
para o bloco de controle.fonte
n4810
Resposta encontrada e atualizada.make_shared
, não dos próprios construtores. Ainda assim, posso usar um membro para pequenos deleters.Eu acredito que isso não é especificado.
Aqui está a especificação dos construtores relevantes: [util.smartptr.shared.const] / 10
Agora, minha interpretação é que, quando a implementação precisa de memória para uso interno, ela o faz usando
a
. Isso não significa que a implementação precise usar essa memória para colocar tudo. Por exemplo, suponha que exista essa implementação estranha:Esta implementação "usa uma cópia
a
para alocar memória para uso interno"? Sim. Ele nunca aloca memória, exceto usandoa
. Há muitos problemas com essa implementação ingênua, mas digamos que ela mude para o uso de alocadores, exceto no caso mais simples, no qual oshared_ptr
arquivo é construído diretamente a partir de um ponteiro e nunca é copiado ou movido ou referenciado de outra forma e não há outras complicações. A questão é que, simplesmente porque não conseguimos imaginar uma implementação válida, por si só não prova que ela não possa existir teoricamente. Não estou dizendo que essa implementação possa realmente ser encontrada no mundo real, apenas que o padrão não parece proibi-lo ativamente.fonte
shared_ptr
para tipos pequenos aloca memória na pilha. E, portanto, não atende aos requisitos padrãostd::move(__d)
e volte paraallocate
quando a cópia for necessária.