Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Чтобы предотвратить исчерпание памяти, по завершении использования ее следует возвратить операционной системе. Для этого используется оператор delete, получающий указатель на освобождаемый объект:
delete p; // p должен быть указателем на динамически созданный объект
// или нулевым указателем
Подобно оператору new, оператор deleteвыполняет два действия: удаляет объект, на который указывает переданный ему указатель, и освобождает соответствующую область памяти.
deleteПередаваемый оператору deleteуказатель должен либо указывать на динамически созданный объект, либо быть нулевым указателем (см. раздел 2.3.2). Результат удаления указателя на область памяти, зарезервированную не оператором new, или повторного удаления значения того же указателя непредсказуем:
int i, *pi1 = &i, *pi2 = nullptr;
double *pd = new double(33), *pd2 = pd;
delete i; // ошибка: i - не указатель
delete pi1; // непредсказуемо: pi1 - локальный
delete pd; // ok
delete pd2; // непредсказуемо: память, на которую указывает pd2,
// уже освобождена
delete pi2; // ok: освобождение нулевого указателя всегда допустимо
Компилятор сообщает об ошибке оператора delete i, поскольку знает, что i — не указатель. Ошибки, связанные с выполнением оператора deleteдля указателей pi1и pd2, коварней: обычно компиляторы неспособны выяснить, указывает ли указатель на объект, созданный статически или динамически. Точно так же компилятор не может установить, была ли уже освобождена память, на которую указывает указатель. Большинство компиляторов примет такие выражения delete, несмотря на их ошибочность.
Хотя значение константного объекта не может быть изменено, сам объект вполне может быть удален. Подобно любым динамическим объектам, константный динамический объект освобождается выполнением оператора deleteдля указателя, указывающего на этот объект:
const int *pci = new const int(1024);
delete pci; // ok: удаляет константный объект
Как упоминалось в разделе 12.1.1, управляемая указателем shared_ptrпамять автоматически освобождается при удалении последнего указателя shared_ptr. Динамический объект, управляемый указателем встроенного типа, существует до тех пор, пока к областям памяти, управляемой при помощи указателей встроенных типов, не будет удален явно.
Функции, возвращающие обычные (а не интеллектуальные) указатели на области динамической памяти, возлагают ответственность за их удаление на вызывающую сторону:
// возвращает указатель на динамически созданный объект
Foo* factory(Т arg) {
// обработать аргумент соответственно
return new Foo(arg); // за освобождение этой памяти отвечает
// вызывающая сторона
}
Подобно прежней версии функции factory()(см. раздел 12.1.1), эта версия резервирует объект, но не удаляет его. Ответственность за освобождение памяти динамического объекта, когда он станет больше не нужен, несет вызывающая сторона функции factory(). К сожалению, вызывающая сторона слишком часто забывает сделать это:
void use_factory(Т arg) {
Foo *p = factory(arg);
// использовать p, но не удалить его
} // p выходит из области видимости, но память,
// на которую он указывает, не освобождается!
Здесь функция use_factory()вызывает функцию factory()резервирующую новый объект типа Foo. Когда функция use_factory()завершает работу, локальная переменная pудаляется. Эта переменная — встроенный указатель, а не интеллектуальный.
В отличие от классов, при удалении объектов встроенного типа не происходит ничего. В частности, когда указатель выходит из области видимости, с объектом, на который он указывает, ничего не происходит. Если этот указатель указывает на динамическую память, она не освобождается автоматически.
Динамическая память, управляемая при помощи встроенных (а не интеллектуальных) указателей, продолжает существование, пока не будет освобождена явно.
В этом примере указатель pбыл единственным указателем на область памяти, зарезервированную функцией factory(). По завершении функции use_factory()у программы больше нет никакого способа освободить эту память. Согласно общей логике программирования, следует исправить эту ошибку и напомнить о необходимости освобождения памяти в функции use_factory():
void use_factory(Т arg) {
Foo *p = factory(arg);
// использование p
delete p; // не забыть освободить память сейчас, когда
// она больше не нужна
}
Если созданный функцией use_factory()объект должен использовать другой код, то эту функцию следует изменить так, чтобы она возвращала указатель на зарезервированную ею память:
Foo* use_factory(Т arg) {
Foo *p = factory(arg);
// использование p
return p; // освободить память должна вызывающая сторона
}
Есть три общеизвестных проблемы, связанных с использованием операторов newи deleteпри управлении динамической памятью:
1. Память забыли освободить. Когда динамическая память не освобождается, это называется "утечка памяти", поскольку она уже не возвращается в пул динамической памяти. Проверка утечек памяти очень трудна, поскольку она обычно не проявляется, пока приложение, проработав достаточно долго, фактически не исчерпает память.
2. Объект использован после удаления. Иногда эта ошибка обнаруживается при создании нулевого указателя после удаления.
3. Повторное освобождение той же памяти. Эта ошибка может произойти в случае, когда два указателя указывают на тот же динамически созданный объект. Если оператор deleteприменен к одному из указателей, то память объекта возвращается в пул динамической памяти. Если впоследствии применить оператор deleteко второму указателю, то динамическая память может быть нарушена.
Допустить эти ошибки значительно проще, чем потом найти и исправить.
Избежать всех этих проблем при использовании исключительно интеллектуальных указателей не получится. Интеллектуальный указатель способен позаботиться об удалении памяти только тогда, когда не останется других интеллектуальных указателей на эту область памяти.
Интервал:
Закладка: