Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
class Sales_data {
public:
// не делать ничего, кроме удаления переменных-членов,
// осуществляемого автоматически
~Sales_data() { }
// другие члены как прежде
};
Переменные-члены автоматически удаляются после выполнения (пустого) тела деструктора. В частности, деструктор класса stringбудет выполнен для освобождения памяти, используемой переменной-членом bookNo.
Важно понять, что само тело деструктора не удаляет переменные-члены непосредственно. Они удаляются в ходе неявной фазы удаления, которая следует за телом деструктора. Тело деструктора выполняется в дополнение к удалению членов, осуществляемому в ходе удаления объекта.
Упражнение 13.9. Что такое деструктор? Что делает синтезируемый деструктор? Когда деструктор синтезируется?
Упражнение 13.10. Что произойдет при удалении объекта класса StrBlob? А класса StrBlobPtr?
Упражнение 13.11. Добавьте деструктор в класс HasPtrиз предыдущих упражнений.
Упражнение 13.12. Сколько вызовов деструктора происходит в следующем фрагменте кода?
bool fcn(const Sales_data *trans, Sales_data accum) {
Sales_data item1(*trans), item2(accum);
return item1.isbn() != item2.isbn();
}
Упражнение 13.13. Наилучший способ изучения функций-членов управления копированием и конструкторов — это определить простой класс с этими функциями-членами, каждая из которых выводит свое имя:
struct X {
X() {std::cout << "X()" << std::endl;}
X(const X&) {std::cout << "X(const X&)" << std::endl;}
};
Добавьте в структуру Xоператор присвоения копии и деструктор, а затем напишите программу, использующую объекты класса Xразличными способами: передайте их как ссылочный и не ссылочный параметры; динамически зарезервируйте их; поместите в контейнеры и т.д. Изучайте вывод, пока не начнете хорошо понимать, когда и почему используется каждая функция-член управления копированием. По мере чтения вывода помните, что компилятор может обойти вызовы конструктора копий.
13.1.4. Правило три/пять
Как уже упоминалось, существуют три базовых функции, контролирующих копирование объектов класса: конструктор копий, оператор присвоения копии и деструктор. Кроме того, как будет продемонстрировано в разделе 13.6, по новому стандарту класс может также определить конструктор перемещения и оператор присваивания при перемещении.
Определять все эти функции не обязательно: вполне можно определить один или два из них, не определяя все. Эти функции можно считать модулями. Если нужен один, не обязательно определять их все.
Вот эмпирическое правило, используемое при принятии решения о необходимости определения в классе собственных версий функций-членов управления копированием: сначала следует решить, нужен ли классу деструктор. Зачастую потребность в деструкторе более очевидна, чем потребность в операторе присвоения или конструкторе копий. Если класс нуждается в деструкторе, он почти наверняка нуждается также в конструкторе копий и операторе присвоения копии.
Используемый в упражнениях класс HasPtrотлично подойдет для примера (см. раздел 13.1.1). Этот класс резервирует динамическую память в конструкторе. Синтезируемый деструктор не будет удалять указатель-член. Поэтому данный класс должен определить деструктор для освобождения памяти, зарезервированной конструктором.
Хоть это и не очевидно, но согласно эмпирическому правилу класс HasPtrнуждается также в конструкторе копий и операторе присвоения копии.
Давайте посмотрим, что было бы, если бы у класса HasPtrбыл деструктор и синтезируемые версии конструктора копий и оператора присвоения копии:
class HasPtr {
public:
HasPtr(const std::string &s = std::string()):
ps(new std::string(s)), i(0) { }
~HasPtr() { delete ps; }
// ошибка: HasPtr нуждается в конструкторе копий и операторе
// присвоения копии
// другие члены, как прежде
};
В этой версии класса зарезервированная в конструкторе память будет освобождена при удалении объекта класса HasPtr. К сожалению, здесь есть серьезная ошибка! Данная версия класса использует синтезируемые версии операторов копирования и присвоения. Эти функции копируют указатели-члены, а значит, несколько объектов класса HasPtrсмогут указывать на ту же область памяти:
HasPtr f(HasPtr hp) // HasPtr передан по значению, поэтому он
// копируется
{
HasPtr ret = hp; // копирует данный HasPtr
// обработка ret
return ret; // ret и hp удаляются
}
Когда функция f()завершает работу, объекты hpи retудаляются и деструктор класса HasPtrвыполняется для каждого из них. Этот деструктор удалит указатель-член и в объекте ret, и в объекте hp. Но эти объекты содержат одинаковое значение указателя. Код удалит тот же указатель дважды, что является серьезной ошибкой (см. раздел 12.1.2) с непредсказуемыми результатами.
Кроме того, вызывающая сторона функции f()может все еще использовать переданный ей объект:
HasPtr p("some values");
f(p); // по завершении f() память, на которую указывает p.ps,
// освобождается
HasPtr q(p); // теперь и p, и q указывают на недопустимую память!
Память, на которую указывает указатель p(и q), больше недопустима. Она была возвращена операционной системе, когда был удален объект hp(или ret)!
Если класс нуждается в деструкторе, он почти наверняка нуждается также в операторе присвоения копии и конструкторе копий.
Хотя большинству классов требуется определить все функции-члены управления копированием (или ни один из них), у некоторых классов есть необходимость только в копировании или присвоении объектов, но нет никакой необходимости в деструкторе.
В качестве примера рассмотрим класс, присваивающий каждому своему объекту уникальный последовательный номер. Такому классу нужен конструктор копий для создания нового уникального последовательного номера для создаваемого объекта. Этот конструктор копировал бы все остальные переменные-члены заданного объекта. Класс нуждался бы также в собственном операторе присвоения копии, чтобы избежать присвоения объекту слева последовательного номера. Однако у этого класса не было бы никакой потребности в деструкторе.
Читать дальшеИнтервал:
Закладка: