Lo siguiente, por supuesto, no es del todo preciso. Tómelo con un grano de sal cuando lo lea :)
Bueno, las tres cosas a las que se refiere son la duración del almacenamiento automático, estático y dinámico , que tiene algo que ver con la duración de los objetos y cuándo comienzan.
Duración de almacenamiento automático
Utiliza el tiempo de almacenamiento automático de breve duración y pequeñas de datos, que solamente se necesita a nivel local dentro de algún bloque:
if(some condition) {
int a[3]; // array a has automatic storage duration
fill_it(a);
print_it(a);
}
La vida útil finaliza tan pronto como salgamos del bloque, y comienza tan pronto como se define el objeto. Son el tipo más simple de duración de almacenamiento y son mucho más rápidos que en la duración de almacenamiento dinámico en particular.
Duración de almacenamiento estático
Utiliza la duración del almacenamiento estático para las variables libres, a las que puede acceder cualquier código en todo momento, si su alcance permite dicho uso (alcance del espacio de nombres), y para las variables locales que necesitan extender su vida útil a través de la salida de su alcance (alcance local), y para las variables miembro que deben ser compartidas por todos los objetos de su clase (alcance de clases). Su vida útil depende del alcance en el que se encuentren. Pueden tener un alcance de espacio de nombres y un alcance local y de clase . Lo que es cierto acerca de ambos es que, una vez que comienza su vida, la vida termina al final del programa . Aquí hay dos ejemplos:
// 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;
}
El programa se imprime ababab
porque localA
no se destruye al salir de su bloque. Puede decir que los objetos que tienen alcance local comienzan su vida útil cuando el control alcanza su definición . Porque localA
sucede cuando se ingresa el cuerpo de la función. Para los objetos en el ámbito del espacio de nombres, la vida comienza al inicio del programa . Lo mismo es cierto para los objetos estáticos de alcance de clase:
class A {
static string classScopeA;
};
string A::classScopeA;
A a, b; &a.classScopeA == &b.classScopeA == &A::classScopeA;
Como puede ver, classScopeA
no está vinculado a objetos particulares de su clase, sino a la clase misma. La dirección de los tres nombres anteriores es la misma, y todos denotan el mismo objeto. Hay una regla especial sobre cuándo y cómo se inicializan los objetos estáticos, pero no nos preocupemos por eso ahora. Eso se entiende por el término fiasco de orden de inicialización estática .
Duración de almacenamiento dinámico
La última duración de almacenamiento es dinámica. Lo usa si desea que los objetos vivan en otra isla, y desea colocar punteros alrededor de ellos. También los usa si sus objetos son grandes y si desea crear matrices de tamaño que solo se conocen en tiempo de ejecución . Debido a esta flexibilidad, los objetos que tienen una duración de almacenamiento dinámico son complicados y lentos de administrar. Los objetos que tienen esa duración dinámica comienzan su vida útil cuando ocurre una nueva invocación apropiada del operador:
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();
}
Su vida útil finaliza solo cuando llamas a eliminar para ellos. Si olvida eso, esos objetos nunca terminan la vida. Y los objetos de clase que definen un constructor declarado por el usuario no tendrán sus destructores llamados. Los objetos que tienen una duración de almacenamiento dinámico requieren un manejo manual de su vida útil y recursos de memoria asociados. Existen bibliotecas para facilitar su uso. La recolección de basura explícita para objetos particulares se puede establecer utilizando un puntero inteligente:
int main() {
shared_ptr<string> s(new string);
foo(s);
}
void foo(shared_ptr<string> s) {
cout << s->size();
}
No tiene que preocuparse por llamar a delete: el ptr compartido lo hace por usted, si el último puntero que hace referencia al objeto se sale del alcance. El ptr compartido tiene una duración de almacenamiento automática. Por lo tanto, su vida útil se administra automáticamente, lo que le permite verificar si debe eliminar el objeto dinámico señalado en su destructor. Para referencia de shared_ptr, consulte los documentos de impulso: http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/shared_ptr.htm