Apontadores e memória
Endereços, aliases, limites, duração de vida, new e delete, propriedade e RAII.
Copiar seta ou objeto?
int a = 3, b = 8;
int* p = &a;
int* q = p; // copia o endereço, não o inteiro
*q += 2; // a passa a 5
p = &b; // só p muda de destino
*p -= 1; // b passa a 7; *q continua 5
| Declaração | Muda destino? | Altera por esse acesso? |
|---|---|---|
int* | Sim | Sim |
const int* | Sim | Não |
int* const | Não | Sim |
const int* const | Não | Não |
nullptrtesta-se, não se desreferencia.const int*não congela um original modificável: outro acesso pode alterá-lo.- A conversão que retira
constnão é, por si, comportamento indefinido. Escrever através do acesso obtido é indefinido se o objeto era originalmenteconst.
Limites e vida
p + iavançaielementos no mesmo array.p[i]é*(p + i).[inicio, fim)inclui o início e exclui o fim. O fim marca, não se lê.- Automático morre no fim do bloco. Dinâmico vive até o dono destruir.
- Devolver
&localdeixa endereço pendente. p->campoé(*p).campo. Nós ligam-se porseguinte, não porp + 1.
Libertar lista dinâmica: guarda o seguinte antes de apagar o atual.
while (atual != nullptr) {
No* seguinte = atual->seguinte;
delete atual;
atual = seguinte;
}
Quem liberta?
| Reserva | Libertação |
|---|---|
new T(...) | delete |
new T[n] | delete[] |
- Trocar as formas é indefinido.
newnormal lançabad_allocse falha. - Não apliques
deletea automáticos.delete nullptrnão faz nada. - Depois de
delete p, os outros acessos a esse objeto ficam pendentes. Atribuirp = nullptrsó limpa esse nome.
RAII: o dono liberta na saída do âmbito, incluindo por exceção.
auto primeiro = std::make_unique<int>(7);
int* observador = primeiro.get(); // só observa
auto segundo = std::move(primeiro); // segundo passa a dono
unique_ptr não se copia. shared_ptr partilha com custo. weak_ptr observa sem prolongar.