Às vezes, quero delegar a construção de objetos que uma classe possui para uma função separada. Algo como
Vertex* new_vertex(const Options& options) {
// do stuff...
return new Vertex(...);
}
onde a função se destina apenas a ser usada dentro de uma classe que possui o Vertex
. Claramente, essa função pode causar alguma confusão de vazamento de memória, por isso quero deixar o mais claro possível. Existe uma convenção de nomenclatura para essas funções?
c++
coding-standards
Shep
fonte
fonte
// TODO: Fix allocation of raw pointer.
unique_ptr
chamada de suarelease()
função e usar os ponteiros brutos como nos velhos métodos.// FIXME: Allocation of raw pointer
?new_vertex
então eu sei que o objeto foi cunhado recentemente. Você poderia chamá-loCreate_new_vertex
para ficar mais claro. Quanto à idéia de que você não deve gerenciar a memória heap sem ponteiros inteligentes, nunca viu a verdade nisso - na verdade, se você não pode gerenciar a memória heap sem eles, também não há negócios em gerenciar a memória heap com eles!Respostas:
Retornar a
unique_ptr
:Só pode haver um que
unique_ptr
aponte para um determinado objeto (a menos que você o abuse ao transmitir para umVertex*
e para trás, de qualquer maneira). Você nunca pode copiar umunique_ptr
, apenas movê-lo. Quando umunique_ptr
é destruído (e não foi removido), eledelete
é o objeto para você.make_unique
cria um novoVertex
e envolve-o em umunique_ptr
; os argumentos aos quais você passamake_unique
são os argumentos que passa para o construtor.fonte
unique_ptr
faça isso. Se tem que ser um nome por algum motivo, acho que não, mas por que tem que ser um nome?std::make_unique
? Isso é unneccessarily detalhado e propenso a erros ...Não, não existe uma "maneira padrão" (mas há uma política de design de API atualmente considerada "prática recomendada").
Devido a essa ambiguidade ("o que uma função que retorna um ponteiro quer que eu faça com ela?"), Atualmente é considerado uma boa prática impor a política de duração e propriedade, por meio do tipo de retorno:
<vertex pointer type>
pode serstd::unique_ptr
("new_vertex não possui o ponteiro") oustd::shared_ptr
("o código do cliente não possui o ponteiro") ou qualquer outra coisa que tenha definido claramente a semântica de propriedade (por exemplo,Vertex const * const
indicaria para o código do cliente "leia o endereço e valores, mas não altere nem exclua o ponteiro ").Geralmente, você não deve retornar um ponteiro bruto (mas, em alguns casos, "a praticidade supera a pureza").
TLDR : existe uma prática recomendada ( sim ), mas não uma maneira padrão (no idioma).
Editar :
Se a classe possuir o Vertex, eu escreveria assim:
fonte
Sim, existem dezenas de "padrões" sobre isso
A resposta que recomenda
unique_ptr
é provavelmente a melhor resposta, mas se você estiver olhando para indicadores brutos, todos desenvolveram seu próprio padrão.De um modo geral funções de chamada
create_____
ounew______
oualloc_____
tendem a implicar um novo objeto.Contudo
Considere que você está misturando comportamentos. Você realmente não se importa se essa é uma nova instância de um objeto ou não. O que importa é se o chamador é responsável por destruir o objeto ou não. Existem muitas APIs que assumem a responsabilidade por um objeto existente e essas funções precisarão de um esquema de nomenclatura correspondente. Talvez
give______
.Se você deseja se afastar um pouco do C ++ ...
Se você deseja considerar o Objective-C como semelhante ao C ++ como fonte de resposta, na verdade há uma resposta real nessa linguagem. Objective-C gerencia a vida útil dos objetos usando contagens de referência. Eles precisavam de uma maneira de descrever se você estava sendo responsabilizado por um objeto ou apenas uma referência a um objeto existente. Se você errar a resposta, errará as contagens de referências e perderá objetos. Dessa forma, eles estabeleceram uma regra: todo objeto retornado pertence a outra pessoa (portanto, você deve aumentar e diminuir a contagem de referências), exceto as chamadas de criação que passam um ponteiro já incrementado para você (você só precisa diminuir). Essas chamadas foram identificadas pelo nome do método. Métodos começando com
alloc
new
copy
oumutableCopy
sempre retornava um novo objeto. Então, o padrão foi imposto pelo idioma.fonte