Скачиваний:
62
Добавлен:
05.07.2021
Размер:
94.13 Кб
Скачать

Лекция 3

Переменные определенные вне тела функции инициализируются нулем. Инициализированные внутри функции переменные встроенного типа остаются не проинициализированными. Попытка копирования или получения значения (доступа) являются ошибкой.

Инициализацию объекта типа класса контролирует класс. Это определяется в конструкторе класса. Большинство встроенных классов позволяет определять объекты без явных инициализаторов. Однако некоторые классы требуют явной инициализации объекта (иначе ошибка компиляции).

По умолчанию создаваемые в динамической памяти объекты инициализируются по умолчанию. Т.е. у локальных объектов встроенного типа будет не валидное значение, а объекты типа класса будут инициализированы конструктором по умолчанию.

Для типов классов, определяющих собственные конструкторы запрос инициализации значением по умолчанию не имеет последствий, т.к. объект инициализируется конструктором класса (стандартным).

Различие существенно в случае встроенных типов:

Инициализация объектов значением по умолчанию присваивает ему конкретное значение, а инициализация по умолчанию – нет. Когда предоставляется инициализатор в круглых скобках для вывода объекта, который предстоит зарезервировать можно использовать ключевое слово auto, но только с одиночным инициализатором в круглых скобках.

Для резервирования константных объектов можно использовать оператор new. Подобно любым константным объектам, динамически созданный константный объект необходимо проинициализировать. Это можно сделать неявно (при наличии конструктора по умолчанию).

Исчерпание памяти

Как только программа использует всю доступную ей память выражения с new будут терпеть неудачу. Если new не способен зарезервировать требуемый объем, он передает исключение типа BadAlloc.

Выражение оператора new позволяет передать дополнительные аргументы. Первый – количество, второй – значение. nothrow указывает, что оператор не должен передавать исключения. Если эта форма оператора new не способна зарезервировать нужный объем, то возвращает нулевой указатель.

Чтобы предотвратить исчерпание памяти при завершении ее использования следует использовать оператор delete, который удаляет объект на который указывает указатель и освобождает область памяти. Передаваемый указатель может быть создан или с new, или быть нулевым. Результат удаления объекта, зарезервированного не оператором new непредсказуем.

Обычный компилятор не способен вычислить, указывает ли указатель на статический объект или на динамический. Подобно любым динамическим объектам, константный динамический объект нужно освобождать вызовом delete. Управляемая указателем shared_ptr память освобождается автоматически с использованием delete при удалении последнего указателя типа shared_ptr.

Динамическая память, управляемая с помощью встроенных, а не интеллектуальных указателей существует пока не будет освобождена явно.

3 проблемы new-delete:

- память забыли освободить

- объект использован после удаления

- повторное освобождение одной и той же памяти

После использования delete указатель становится недопустимым. Но он продолжает держать в себе адрес уже освобожденной памяти. Проблему можно избежать, освободив связанную с ним память непосредственно перед выходом из области видимости этого указателя. После применения delete указателю можно присвоить null_ptr, говорящее о том, что указатель не указывает на объект.

Если не инициализировать интеллектуальный указатель, то он инициализируется как нулевой. Smart-pointer можно инициализировать указателем, возвращенным оператором new. Конструкции smart-pointera, получающие параметры, являются явными, значит нельзя неявно преобразовать встроенный указатель в интеллектуальный. Для этого необходимо использовать явную форму инициализации.

Функция, возвращающая указатель типа shared_ptr не может неявно преобразовать простой указатель в своем операторе return.

По умолчанию, указатель, используемый для инициализации smart-pointera, должен указывать на область динамической памяти, поскольку используют оператор delete для освобождения связанного с ними объекта. Вместо оператора delete можно передать собственную функцию освобождения ресурсов. Рекомендуется использовать функцию make_shared для создания shared_ptr, а не new, т.к. эта функция корректно создает копию указателя.

Не стоит использовать встроенный указатель для обращения к smart-pointer, потому что нельзя быть уверенным, что объект еще не удален.

Метод reset() модифицирует счетчик ссылок, а если достиг нуля – удаляет объект. Его целесообразно использовать с методом unique() для контроля совместного использования объекта несколькими указателями.

3 мар 2021