Tem std::make_unique
algum benefício em eficiência como std::make_shared
?
Comparado à construção manual std::unique_ptr
:
std::make_unique<int>(1); // vs
std::unique_ptr<int>(new int(1));
c++
c++11
c++14
smart-pointers
unique-ptr
NFRCR
fonte
fonte
make_shared
alguma eficiência em escrever apenas o código da mão longa?make_shared
pode alocar o espaço para o objeto e o espaço para o bloco de controle juntos em uma única alocação. O custo disso é que o objeto não pode ser desalocado separadamente do bloco de controle; portanto, se você usaweak_ptr
muito, pode acabar usando mais memória.Respostas:
A motivação por trás
make_unique
é basicamente dupla:make_unique
é seguro para criar temporários, enquanto que com o uso explícito denew
você é necessário lembrar a regra de não usar temporários sem nome.A adição de
make_unique
finalmente significa que podemos dizer às pessoas para 'nunca' usarem,new
em vez da regra anterior, para '' nunca 'usar,new
exceto quando você faz umunique_ptr
'.Há também uma terceira razão:
make_unique
não requer uso de tipo redundante.unique_ptr<T>(new T())
->make_unique<T>()
Nenhum dos motivos envolve a melhoria da eficiência do tempo de execução da maneira que o uso
make_shared
(devido a evitar uma segunda alocação, ao custo do uso de memória potencialmente mais alto).* É esperado que o C ++ 17 inclua uma alteração de regra que signifique que isso não é mais seguro. Consulte os documentos do comitê C ++ P0400R0 e P0145R3 .
fonte
std::unique_ptr
estd::shared_ptr
é por isso que podemos dizer às pessoas para "nunca usaremnew
".make_shared
e tambémmake_unique
a peça final que estava faltando anteriormente.f
:f(unique_ptr<T>(new T), function_that_can_throw());
- para citar a resposta: O compilador é permitido a chamada (em ordem):new T
,function_that_can_throw()
,unique_ptr<T>(...)
. Obviamente, sefunction_that_can_throw
realmente joga, então você vaza.make_unique
impede este caso. Então, minha pergunta é respondida.std::make_unique
estd::make_shared
existem por dois motivos:std::unique_ptr
oustd::shared_ptr
construtores. (Veja a seção Notas aqui .)Não se trata realmente de eficiência de tempo de execução. Há um pouco sobre o bloco de controle e a
T
atribuição de todos de uma vez, mas acho que isso é mais um bônus e menos uma motivação para que essas funções existam.fonte
std::make_shared
garantirá que pelo menos um deles seja empacotado no ponteiro inteligente antes que a outra alocação de memória ocorra, portanto, não haverá vazamentos.Uma razão pela qual você precisaria usar
std::unique_ptr(new A())
oustd::shared_ptr(new A())
diretamente, em vez destd::make_*()
não conseguir acessar o construtor da classeA
fora do escopo atual.fonte
Considere chamada de função
Suponha que new tenha
A()
êxito, mas newB()
lança uma exceção: você a captura para retomar a execução normal do seu programa. Infelizmente, o padrão C ++ não exige que o objeto A seja destruído e sua memória seja desalocada: a memória vaza silenciosamente e não há como limpá-lo. Ao envolver A e B,std::make_uniques
você tem certeza de que o vazamento não ocorrerá:O ponto aqui é que,
std::make_unique<A>
estd::make_unique<B>
agora são objetos temporários, a limpeza de objetos temporários está especificada corretamente no padrão C ++: seus destruidores serão acionados e a memória liberada. Portanto, se puder, sempre prefira alocar objetos usandostd::make_unique
estd::make_shared
.fonte