Pular para conteúdo

Ponteiros, Vida Útil e Posse

Segurança de memória em C++ exige mais que ponteiro não nulo. Ponteiro ou referência deve designar objeto cuja vida começou, não terminou e permite a operação.

Armazenamento e vida do objeto

Armazenamento fornece bytes alinhados. A vida começa e termina por construção, destruição e regras da linguagem. O armazenamento pode sobreviver ao objeto, e um ponteiro continuar não nulo após o fim.

int* dangling() {
    int local = 42;
    return &local; // local's lifetime ends on return
}

Desreferenciar o resultado é comportamento indefinido. O defeito é de vida útil.

Prefira valores e proprietários com escopo

std::vector<widget> values;                   // owns widget values
auto owner = std::make_unique<widget>();      // exclusive dynamic owner
widget& alias = *owner;                       // non-owning; owner must outlive use

Alocação dinâmica não é exigida só porque o objeto é grande. Use-a quando vida em runtime, polimorfismo, endereço estável, grafo ou requisito explícito exigir indireção.

Aritmética de ponteiros

É definida somente dentro de um array e na posição one-past. Esta pode ser comparada ou usada como sentinela, não desreferenciada. Prefira iteradores, ranges e std::span a pares ponteiro-comprimento.

Contratos de posse

Interface Significado
T Valor independente
T& / T const& Alias obrigatório sem posse
T* / T const* Alias opcional/reposicionável sem posse
std::unique_ptr<T> Transferência de posse exclusiva
std::shared_ptr<T> Posse compartilhada
std::weak_ptr<T> Observação sem posse compartilhada
std::span<T> Intervalo contíguo sem posse

Tipos não codificam toda vida útil. Uma referência ainda pode ficar dangling.

Invalidação

Operações de contêiner invalidam iteradores, ponteiros, referências e views. A realocação de vector invalida todas as referências aos elementos. Leia o contrato específico.

Alocação manual

Pares new/delete e new[]/delete[] falham sob retornos antecipados, exceções e transferências. Encapsule em contêineres, smart pointers, allocators ou recursos auditados.

Exercícios

  1. Identifique dependências de vida em classe com std::string_view.
  2. Explique por que ponteiro não nulo ainda pode ser inválido.
  3. Refatore buffer new[]/delete[] para std::vector.