É mais sutil do que as outras respostas sugerem. Não há uma divisão absoluta entre os dados na pilha e os dados no heap com base em como você os declara. Por exemplo:
std::vector<int> v(10);
No corpo de uma função, que declara um vector
(array dinâmico) de dez números inteiros na pilha. Mas o armazenamento gerenciado pelovector
não está na pilha.
Ah, mas (as outras respostas sugerem) o tempo de vida desse armazenamento é limitado pelo tempo de vida do vector
mesmo, que aqui é baseado em pilha, portanto, não faz diferença como ele é implementado - só podemos tratá-lo como um objeto baseado em pilha com semântica de valores.
Não tão. Suponha que a função fosse:
void GetSomeNumbers(std::vector<int> &result)
{
std::vector<int> v(10);
// fill v with numbers
result.swap(v);
}
Portanto, qualquer coisa com uma swap
função (e qualquer tipo de valor complexo deve ter uma) pode servir como um tipo de referência recuperável para alguns dados de heap, em um sistema que garante um único proprietário desses dados.
Portanto, a abordagem moderna do C ++ é nunca armazenar o endereço de dados de heap em variáveis de ponteiro local simples. Todas as alocações de heap devem estar ocultas dentro das classes.
Se você fizer isso, poderá pensar em todas as variáveis em seu programa como se fossem tipos simples de valor e esquecer completamente o heap (exceto ao escrever uma nova classe de wrapper semelhante a valor para alguns dados de heap, o que deve ser incomum) .
Você apenas precisa reter um conhecimento especial para ajudá-lo a otimizar: sempre que possível, em vez de atribuir uma variável a outra como esta:
a = b;
troque-os assim:
a.swap(b);
porque é muito mais rápido e não gera exceções. O único requisito é que você não precise b
continuar com o mesmo valor (isso vai gerara
o valor, que seria descartado a = b
).
A desvantagem é que essa abordagem obriga a retornar valores de funções por meio de parâmetros de saída em vez do valor de retorno real. Mas eles estão corrigindo isso no C ++ 0x com referências rvalue .
Nas situações mais complicadas de todas, você levaria essa idéia ao extremo geral e usaria uma classe de ponteiro inteligente como a shared_ptr
que já está em tr1. (Embora eu argumente que, se você precisar, pode ter se mudado para o ponto ideal de aplicabilidade do Standard C ++.)