Ponteiro inteligente
Em ciência da computação, um apontador inteligente (também conhecido pelo termo em língua inglesa smart pointer) é um tipo de dado abstrato que simula um apontador. Ele fornece mais funcionalidades que ponteiros, como coletor de lixo ou verificação de limites do tipo de dado, para adicionar segurança e reduzir erros de programação, ainda que maximizando a eficiência. Implementações de ponteiros inteligentes geralmente possuem referência aos objetos que apontam por questões de gerenciamento de memória. Do ponto de vista de padrões de projeto de software, um ponteiro inteligente é um proxy para uma interface de ponteiro.
Contagem de referências
O uso de ponteiros pode ser fonte de erros de programação, como o vazamento de memória. Ponteiros inteligentes podem ser usados para prevenir esse problema ao tornar a desalocação do recurso um procedimento automático. Quando o ponteiro de um objeto é destruído, ou ainda o último ponteiro de uma série apontando para o mesmo objeto, o objeto apontado é também destruído. Seu funcionamento interno pode variar, com técnicas que variam desde contagem de referências ao objeto ou a atribuição da propriedade de um objeto a um único ponteiro.
Uso prático
Em C++, um ponteiro inteligente pode ser implementado como uma classe que simula o comportamento de ponteiros tradicionais, através do uso de sobrecarga de operadores, mas cujo funcionamento interno (encapsulado) é mais sofisticado. A própria biblioteca padrão declara no cabeçalho <memory> os ponteiros inteligentes std::unique_ptr e std::shared_ptr.
Também pode ser usado pelo Object Pascal(FPC ou Delphi) usando TSmartPointer.
Exemplo
Em C++, seja SmartPointer<X> uma classe de ponteiro inteligente especializada para a classe X:
void teste_de_ponteiro_inteligente()
{
// Cria-se dois objetos e mantém-se ponteiros tradicionais para referenciá-los
Object* obj_1 = new Object();
Object* obj_2 = new Object();
// Declara-se dois ponteiros inteligentes e associa-se aos objetos alocados anteriormente
// A contagem interna de referências para obj_1 e obj_2 será 1
SmartPointer<Object> p = obj_1;
SmartPointer<Object> q = obj_2;
// Atribui-se p a q, o que torna a contagem interna de referência a obj_1 igual a 2
// obj_2 será destruído já que a contagem de referências chega a 0
q = p;
// Atribui-se nulo a q. A contagem de obj_1 retorna a 1
q = NULL;
// Cria-se novo objeto e atribui-se diretamente a p
// obj_1 é destruído
p = new Object();
// Cria-se outro objeto e atribui-se a um ponteiro tradicional
// Na perda de escopo do ponteiro, obj_3 será perdido e haverá vazamento de memória
Object* obj_3 = new Object();
}
Object Pascal:(o mesmo exemplo acima)
1 procedure teste_de_ponteiro_inteligente;
2 var
3 obj_1 : Object;
4 obj_2 : Object;
5 obj_3 : TSmartPointer<Object>
6 p: TSmartPointer<Object>
7 q: TSmartPointer<Object>
8 begin
9 // Cria-se dois objetos e mantém-se ponteiros tradicionais para referenciá-los
10 obj_1 := Object.Create;
11 obj_2 := Object.Create;
12
13 // Declara-se dois ponteiros inteligentes e associa-se aos objetos alocados anteriormente
14 // A contagem interna de referências para obj_1 e obj_2 será 1
15 //SmartPointer<Object> p = obj_1;
16 p.Create(Object.Create); //implícito
17 //SmartPointer<Object> q = obj_2;
18 q := TSmartPointer<Object>.Create(obj_2); //explícito
19
20 // Atribui-se p a q, o que torna a contagem interna de referência a obj_1 igual a 2
21 // obj_2 será destruído já que a contagem de referências chega a 0
22 p := q;
23
24 // Atribui-se nulo a q. A contagem de obj_1 retorna a 1
25 q := nil;
26
27 // Cria-se novo objeto e atribui-se diretamente a p
28 // obj_1 é destruído
29 p := TSmartPointer<Object>.Create(Object.Create);
30
31 // Cria-se outro objeto e atribui-se a um ponteiro tradicional
32 // Na perda de escopo do ponteiro, obj_3 será perdido e haverá vazamento de memória
33 obj_3 := Object.Create;
34 end;