Então digamos que eu tenha uma estrutura de árvore, com um nó definido como:
struct Node
{
byte key_part;
unique_ptr<Node> left, right, middle;
TValue value;
};
unique_ptr<Node> root;
A semântica aqui está correta, eu absolutamente não quero que outros tenham acesso ao meu nó em si. Ele é mantido exclusivamente pela minha árvore.
No entanto, quero adicionar uma função auxiliar interna para pesquisar a árvore com base na semântica interna e retornar um ...algo? para a estrutura do nó. Esta é uma função privada, usada apenas internamente para inserir um nó e preenchê-lo com dados de fora, excluir um nó ou retornar o value
campo (não o nó em si) para fora. O nó não vaza para fora de forma alguma.
Então como eu escrevo a função? Não posso retornar unique_ptr<Node>
dela, certo? Ou a semântica de movimento entrará em ação. Eu poderia retornar um ponteiro, mas isso parece quebrar o sistema, além de levar a problemas de aliasing. Uma referência é semelhante, mas me impede de usar nullptr
para marcar nenhum resultado encontrado. Em essência, qual seria o tipo de retorno disto:
/* return type here */ search(const span<byte>& key)
{
auto node = /* recursive search here, etc */;
return /* what do I put here, given I have a unique_ptr<Node> reference? */;
}
Basta retornar um ponteiro bruto. Ponteiros brutos são a representação canônica de uma referência anulável não proprietária, que é exatamente o que você quer.
Para maior segurança, consulte as Diretrizes Básicas do C++ sobre este assunto.
Não quebra nada.
Problemas de aliasing surgem quando você tem:
O exemplo clássico disso é a distinção entre
memcpy
(que pressupõe intervalos não sobrepostos) ememmove
(que precisa tomar precauções extras para lidar com intervalos possivelmente sobrepostos).O uso de um ponteiro bruto ou inteligente não afeta isso em nada.