него. Размещение происходит в стеке программмы.
static
-
объект размещается
при запуске программы и удаляется из памяти при её завершении. Размещение
происходит в BSS сегменте памяти программы.
thread
-
объект размещается
при запуске потока и удаляется из памяти при его завершении.
dynamic
-
объект
размещается и удаляется при вызове функций динамической памяти.
Размещение происходит в свободной динамической памяти программы (heap)
A a1; // static -
глобальный объект, создаваемый при запуске
//
проограммы в момент "до его первого использования"
static A a2; // static -
то же самое, только область видимости
//
ограничена данным модулем трансляции
int main()
{
{
A a2; // automatic -
объект создается в момент
//
объявления и существует до конца исполнения
//
блока или функции
}
//здесь объект 'a' будет разрушен идалее он недоступен
{
static A a3; // static -
объект создается при запуске
//
программы, инициализируется конструктором по
//
умолчанию (переменные фундаментальных типов
//
инициализируются 0), существует постоянно до
//
завершения программы, доступ данном случае
//
только локальный т.к. объект объявлен в блоке
extern A a4;
// объявление, не приводящее к размещению
//
в памяти.
register A a5; // automatic -
объект существует в области
//
видимости, по возможности в регистровой
//
памяти процессора
thread_local A a6; // thread -
объект существует во время исполнения
//
потока. здесь поток один - основной поток,
//
в котором выполняется main()
}
}
Объекты могут быть созданы в любой момент в динамической памяти
глобальными функциями размещения
void* operator new(std::size_t);
void* operator new[](std::size_t);
и удалены соответствующими им функциями удаления:
void operator delete(void*);
void operator delete[](void*);
Пример
int main()
{
51
A *a = new A;
// создание объекта в памяти.
// Можно написать A *a = new A(); - в обоих слуаях будет вызван
//
конструктор по умолчанию 'A()'.
// ... использование объекта
delete a;
// удаление объекта из памяти. Дальнейшее использование
//
невозможно несмотря на то, что укаазатель 'a' продолжает
//
хранить адрес. Удаление строго обязательно!
}
В случае automatic, static и thread компилятор самостоятельно создаст и
удалит такие объекты по перечисленным выше правилам. В
случае
динамического размещения, забота о своевременном создании и удалении
объектов лежит на разработчике программы, которому
придется решить две
возникающие проблемы: неудаление созданных и больше не используемых
объектов, приводящее к непроизводительному задействованию ресурсов,
например, утечкее памяти, и несвоевременное удаление объектов, которые еще
используются в программе. Для избежания таких ситуаций существуют
интеллектуальные,
или умные, указатели (smart pointers). Такие указатели
реализованы как классы, точнее шаблоны классов, и
обеспечивают
своевременное автоматческое удаление объекта без явного вызова 'delete'.
Интеллектуальные указатели упрощают работу программиста и страхуют от
ошибок. Код программы выглядит как в языках со сбором мусора (garbage
collection) -
процессом автоматического уничтожения неиспользуемых
объектов.
Предыдущий пример с обязательным удалением указателя с применением
интеллектуального указателя 'unique_ptr' становится существенно более
лаконичным:
#include
// заголовок стандартной библиотеки необходим для
//
использования интеллектуальных указателей
int main()
{
unique_ptr a(new A);
// создание объекта в памяти и передача
//
полученного указателя в интеллектуальный
//
указатель
// ... использование объекта точно такое же, как если бы 'a' был простым
//
указателем. Тут может быть столько кода, что автор может забыть,
что
//
ему надо что-то удалять
// А удалять объект и не требуется. Интеллектуальный указатель
//
удалит его сам
}
Уникальные указатели не могут быть скопированы (на то они и
уникальные), но могут быть переданы с помощью перемещения.
52