Obviamente, o seguinte não é totalmente preciso. Tome-o com um grão de sal quando o ler :)
Bem, as três coisas a que você se refere são a duração automática, estática e dinâmica do armazenamento , que tem algo a ver com o tempo de vida dos objetos e quando eles começam a vida.
Duração de armazenamento automático
Você usa a duração automática do armazenamento para dados pequenos e de curta duração , necessários apenas localmente em algum bloco:
if(some condition) {
int a[3]; // array a has automatic storage duration
fill_it(a);
print_it(a);
}
A vida útil termina assim que saímos do bloco e inicia assim que o objeto é definido. Eles são o tipo mais simples de duração do armazenamento e são muito mais rápidos do que em particular a duração dinâmica do armazenamento.
Duração de armazenamento estático
Você usa a duração do armazenamento estático para variáveis livres, que podem ser acessadas por qualquer código o tempo todo, se seu escopo permitir esse uso (escopo de namespace) e para variáveis locais que precisam estender sua vida útil pela saída de seu escopo (escopo local) e para variáveis de membro que precisam ser compartilhadas por todos os objetos de sua classe (escopo de classes). A vida útil deles depende do escopo em que estão. Eles podem ter escopo de espaço para nome e escopo local e escopo de classe . O que é verdade sobre os dois é que, assim que a vida começa, a vida termina no final do programa . Aqui estão dois exemplos:
// static storage duration. in global namespace scope
string globalA;
int main() {
foo();
foo();
}
void foo() {
// static storage duration. in local scope
static string localA;
localA += "ab"
cout << localA;
}
O programa é impresso ababab
, porque localA
não é destruído na saída de seu bloco. Você pode dizer que objetos com escopo local começam a vida útil quando o controle atinge sua definição . Pois localA
isso acontece quando o corpo da função é inserido. Para objetos no escopo do espaço para nome, o tempo de vida começa na inicialização do programa . O mesmo vale para objetos estáticos do escopo da classe:
class A {
static string classScopeA;
};
string A::classScopeA;
A a, b; &a.classScopeA == &b.classScopeA == &A::classScopeA;
Como você vê, classScopeA
não está vinculado a objetos específicos de sua classe, mas à própria classe. O endereço dos três nomes acima é o mesmo e todos denotam o mesmo objeto. Existem regras especiais sobre quando e como os objetos estáticos são inicializados, mas não vamos nos preocupar com isso agora. Isso significa o termo fiasco da ordem de inicialização estática .
Duração de armazenamento dinâmico
A última duração do armazenamento é dinâmica. Você o usa se quiser que os objetos morem em outra ilha e queira colocar indicadores em torno deles. Você também os utiliza se seus objetos forem grandes e se desejar criar matrizes de tamanho conhecidas apenas em tempo de execução . Devido a essa flexibilidade, objetos com duração de armazenamento dinâmico são complicados e lentos para gerenciar. Objetos com essa duração dinâmica começam a vida útil quando ocorre uma nova chamada de operador apropriada :
int main() {
// the object that s points to has dynamic storage
// duration
string *s = new string;
// pass a pointer pointing to the object around.
// the object itself isn't touched
foo(s);
delete s;
}
void foo(string *s) {
cout << s->size();
}
Sua vida útil termina somente quando você chama delete para eles. Se você esquecer disso, esses objetos nunca terminam a vida útil. E os objetos de classe que definem um construtor declarado pelo usuário não terão seus destruidores chamados. Objetos com duração de armazenamento dinâmico requerem manipulação manual de sua vida útil e recursos de memória associados. Existem bibliotecas para facilitar o uso delas. A coleta de lixo explícita para objetos específicos pode ser estabelecida usando um ponteiro inteligente:
int main() {
shared_ptr<string> s(new string);
foo(s);
}
void foo(shared_ptr<string> s) {
cout << s->size();
}
Você não precisa se preocupar em chamar delete: o ptr compartilhado faz isso por você, se o último ponteiro que faz referência ao objeto ficar fora do escopo. O próprio ptr compartilhado possui duração de armazenamento automático. Portanto, seu tempo de vida é gerenciado automaticamente, permitindo que você verifique se deve excluir o objeto dinâmico apontado para seu destruidor. Para referência shared_ptr, consulte documentos de aumento: http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/shared_ptr.htm