Следующее, конечно, все не совсем точно. Возьми это с крошкой соли, когда читаешь это :)
Итак, три вещи, на которые вы ссылаетесь, - это автоматическое, статическое и динамическое время хранения , которое имеет отношение к тому, как долго живут объекты и когда они начинают жить.
Автоматическая продолжительность хранения
Вы используете автоматическую длительность хранения для коротких и небольших данных, которые необходимы только локально в некотором блоке:
if(some condition) {
int a[3]; // array a has automatic storage duration
fill_it(a);
print_it(a);
}
Время жизни заканчивается, как только мы выходим из блока, и начинается, как только объект определен. Они являются наиболее простым видом продолжительности хранения и намного быстрее, чем, в частности, продолжительность динамического хранения.
Статическая продолжительность хранения
Вы используете статическую длительность хранения для свободных переменных, к которым может обращаться любой код в любое время, если их область допускает такое использование (область пространства имен), и для локальных переменных, которым необходимо продлить срок их жизни при выходе из своей области (локальная область), и для переменных-членов, которые должны быть общими для всех объектов их класса (класс classs). Их срок службы зависит от объема они находятся. Они могут иметь область пространства имен и локальную область и область видимость класса . Что верно для них обоих, так это то, что как только начинается их жизнь, заканчивается жизнь в конце программы . Вот два примера:
// 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;
}
Программа печатает ababab
, потому что localA
не уничтожается при выходе из своего блока. Вы можете сказать, что объекты, имеющие локальную область видимости, начинают время жизни, когда управление достигает своего определения . Ведь localA
это происходит, когда вводится тело функции. Для объектов в области пространства имен время жизни начинается при запуске программы . То же самое верно для статических объектов класса видимости:
class A {
static string classScopeA;
};
string A::classScopeA;
A a, b; &a.classScopeA == &b.classScopeA == &A::classScopeA;
Как видите, classScopeA
привязан не к конкретным объектам своего класса, а к самому классу. Адрес всех трех имен выше одинаков, и все они обозначают один и тот же объект. Существует специальное правило о том, когда и как инициализируются статические объекты, но сейчас не будем об этом беспокоиться. Это подразумевается под термином статический порядок инициализации фиаско .
Динамическая продолжительность хранения
Последняя продолжительность хранения является динамической. Вы используете его, если хотите, чтобы объекты жили на другом острове, и вы хотите поместить указатели вокруг них. Вы также можете использовать их, если ваши объекты большие , и если вы хотите создать массивы размером, известным только во время выполнения . Из-за этой гибкости объекты, имеющие динамическую продолжительность хранения, являются сложными и медленными в управлении. Объекты с такой динамической продолжительностью начинают время жизни, когда происходит соответствующий вызов нового оператора:
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();
}
Его время жизни заканчивается только когда вы вызываете delete для них. Если вы забудете об этом, эти объекты никогда не заканчивают жизнь. И объектам классов, которые определяют объявленный пользователем конструктор, не будут вызываться их деструкторы. Объекты, имеющие динамическую продолжительность хранения, требуют ручной обработки их времени жизни и связанного ресурса памяти. Библиотеки существуют, чтобы облегчить их использование. Явная сборка мусора для определенных объектов может быть установлена с помощью умного указателя:
int main() {
shared_ptr<string> s(new string);
foo(s);
}
void foo(shared_ptr<string> s) {
cout << s->size();
}
Вам не нужно заботиться о вызове delete: общий ptr сделает это за вас, если последний указатель, который ссылается на объект, выходит из области видимости. Сам общий ресурс имеет автоматическую продолжительность хранения. Таким образом, его время жизни автоматически управляется, что позволяет ему проверять, следует ли удалять указанный динамический объект в его деструкторе. Для ссылки на shared_ptr см. Дополнительные документы: http://www.boost.org/doc/libs/1_37_0/libs/smart_ptr/shared_ptr.htm