Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Как и у конструктора копий, у конструктора перемещения есть начальный параметр, являющийся ссылкой на тип класса. В отличие от конструктора копии, ссылочный параметр конструктора перемещения является ссылкой на r-значение. Подобно конструктору копий, у всех дополнительных параметров должны быть аргументы по умолчанию.
Кроме перемещения ресурсов, конструктор перемещения должен гарантировать такое состояние перемещенного объекта, при котором его удаление будет безопасно. В частности, сразу после перемещения ресурса оригинальный объект больше не должен указывать на перемещенный ресурс, ответственность за него принимает вновь созданный объект.
В качестве примера определим конструктор перемещения для класса StrVec, чтобы перемещать, а не копировать элементы из одного объекта класса StrVecв другой:
StrVec::StrVec(StrVec &&s) noexcept // перемещение не будет передавать
// исключений
// инициализаторы членов получают ресурсы из s
: elements(s.elements), first_free(s.first_free), cap(s.cap) {
// оставить s в состоянии, при котором запуск деструктора безопасен
s.elements = s.first_free = s.cap = nullptr;
}
Оператор noexcept(уведомляющий о том, что конструктор не передает исключений) описан ниже, а пока рассмотрим, что делает этот конструктор.
В отличие от конструктора копий, конструктор перемещения не резервирует новую память; он получает ее от заданного объекта класса StrVec. Получив область памяти от своего аргумента, тело конструктора присваивает указателям заданного объекта значение nullptr. После перемещения оригинальный объект продолжает существовать. В конечном счете оригинальный объект будет удален, а значит, будет выполнен его деструктор. Деструктор класса StrVecвызывает функцию deallocate()для указателя first_free. Если забыть изменить указатель s.first_free, то удаление оригинального объекта освободит область памяти, которая была только что передана.
Операции перемещения, библиотечные контейнеры и исключенияПоскольку операция перемещения выполняется при "захвате" ресурсов, она обычно не резервирует ресурсы. В результате операции перемещения обычно не передают исключений. Когда создается функция перемещения, неспособная передавать исключения, об этом факте следует сообщить библиотеке. Как будет описано вскоре, если библиотека не знает, что конструктор перемещения не будет передавать исключений, она предпримет дополнительные меры по отработке возможности передачи исключения при перемещении объекта этого класса.
Один из способов сообщить об этом библиотеке — определить оператор noexceptв конструкторе. Введенный новым стандартом оператор noexceptподробно рассматривается в разделе 18.1.4, а пока достаточно знать, что он позволяет уведомить, что функция не будет передавать исключений. Оператор noexceptуказывают после списка параметров функции. В конструкторе его располагают между списком параметров и символом :, начинающим список инициализации конструктора:
class StrVec {
public:
StrVec(StrVec&&) noexcept; // конструктор перемещения
// другие члены, как прежде
};
StrVec::StrVec(StrVec &&s) noexcept : /* инициализаторы членов */
{ /* тело конструктора */ }
Оператор noexceptследует объявить и в заголовке класса, и в определении, если оно расположено вне класса.
Конструкторы перемещения и операторы присваивания при перемещении, которые не могут передавать исключения, должны быть отмечены как noexcept.
Понимание того, почему необходим оператор noexcept, может помочь углубить понимание того, как библиотека взаимодействует с объектами написанных вами типов. В основе требования указывать, что функция перемещения не будет передавать исключения, лежат два взаимосвязанных факта: во- первых, хотя функции перемещения обычно не передают исключений, им это разрешено. Во-вторых, библиотечные контейнеры предоставляют гарантии относительно того, что они будут делать в случае исключения. Например, класс vectorгарантирует, что, если исключение произойдет при вызове функции push_back(), сам вектор останется неизменным.
Теперь рассмотрим происходящее в функции push_back(). Подобно соответствующей функции класса StrVec(см. раздел 13.5), функция push_back()класса vectorмогла бы потребовать пересоздания вектора. При пересоздании вектор перемещает элементы из прежней своей области памяти в новую, как в функции reallocate()(см. раздел 13.5).
Как только что упоминалось, перемещение объекта обычно изменяет состояние оригинального объекта. Если пересоздание использует конструктор перемещения и этот конструктор передает исключение после перемещения некоторых, но не всех элементов, возникает проблема. Перемещенные элементов в прежнем пространстве были бы изменены, а незаполненные элементы в новом пространстве еще не будут созданы. В данном случае класс vectorне удовлетворял бы требованию оставаться неизменным при исключении.
С другой стороны, если класс vectorиспользует конструктор копий, то при исключении он может легко удовлетворить это требование. В данном случае, пока элементы создаются в новой памяти, прежние элементы остаются неизменными. Если происходит исключение, вектор может освободить зарезервированное пространство (оно могло бы и не быть успешно зарезервировано) и прекратить операцию. Элементы оригинального вектора все еще существуют.
Во избежание этой проблемы класс vectorдолжен использовать во время пересоздания конструктор копий вместо конструктора перемещения, если только не известно , что конструктор перемещения типа элемента не может передать исключение. Если необходимо, чтобы объекты типа были перемещены, а не скопированы при таких обстоятельствах, как пересоздание вектора, то следует явно указать библиотеке, что использовать конструктор перемещения безопасно. Для этого конструктор перемещения (и оператора присваивания при перемещении) следует отметить как noexcept.
Оператор присваивания при перемещении делает то же, что и деструктор с конструктором перемещения. Подобно конструктору перемещения, если оператор присваивания при перемещении не будет передавать исключений, то его следует объявить как noexcept. Подобно оператору присвоения копии, оператор присваивания при перемещении должен принять меры против присвоения себя себе:
Интервал:
Закладка: