Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Копирование осуществляется в операторе returnпри списочной инициализации возвращаемого значения (см. раздел 6.3.2). Указатель-член firstвозвращенной пары указывает на начало зарезервированной памяти; значение для указателя-члена secondвозвращается функцией uninitialized_copy()(см. раздел 12.2.2). Это значение будет указателем на следующий элемент после последнего созданного элемента.
free()У функции-члена free()две обязанности: она должна удалить элементы, а затем освободить пространство, зарезервированное объектом класса StrVec. Цикл forвызывает функцию destroy()класса allocator, перебирая элементы в обратном порядке, начиная с последнего существующего элемента и заканчивая первым:
void StrVec::free() {
// нельзя освободить 0 указателей;
// если элемент нулевой - не делать ничего
if (elements) {
// удалить прежние элементы в обратном порядке
for (auto p = first_free; p != elements; /* пусто */)
alloc.destroy(--p);
alloc.deallocate(elements, cap - elements);
}
}
Функция destroy()запускает деструктор класса string. Деструктор класса stringосвобождает память, занятую самой строкой.
Как только элементы будут удалены, освобождается пространство, зарезервированное классом StrVecпри вызове функции deallocate(). Указатель, передаваемый функции deallocate(), должен быть именно тем, который ранее создал вызов функции allocate(). Поэтому перед вызовом функции deallocate()сначала проверяется, тот ли это elements, а не нулевой.
При наличии функций-членов alloc_n_copy()и free()функции-члены управления копированием нашего класса очень просты.
StrVec::StrVec(const StrVec &s) {
// вызов функции alloc_n_copy() для резервирования количества
// элементов как в s
auto newdata = alloc_n_copy(s.begin(), s.end());
elements = newdata.first;
first_free = cap = newdata.second;
}
Конструктор копий вызывает функцию alloc_n_copy(), а затем присваивает результат вызова переменным-членам. Возвращаемое значение функции alloc_n_copy()является парой указателей. Первый указатель указывает на первый созданный элемент, а второй — на следующий после последнего созданного. Поскольку функция alloc_n_copy()резервирует пространство для точно такого количества элементов, которое было задано, указатель capтакже указывает только на следующий после последнего созданного.
Деструктор вызывает функцию free():
StrVec::~StrVec() { free(); }
Оператор присвоения копии вызывает функцию alloc_n_copy()прежде, чем освободить существующие элементы. Это защищает от копирования в себя самого:
StrVec &StrVec::operator=(const StrVec &rhs) {
// вызов alloc_n_copy() для резервирования точно такого количества
// элементов, как в rhs
auto data = alloc_n_copy(rhs.begin(), rhs.end());
free();
elements = data.first;
first_free = cap = data.second;
return *this;
}
Подобно конструктору копий, оператор присвоения копии использует значения, возвращенные функцией alloc_n_copy(), для инициализации своих указателей.
Перемещение, а не копирование элементов при резервированииПрежде чем приступить к функции reallocate(), следует обдумать то, что она должна делать:
• зарезервировать память для нового, большего массива строк;
• заполнить первую часть этого пространства существующими элементами;
• удалить элементы в существующей памяти и освободить ее.
Глядя на этот список, можно заметить, что пересоздание объекта класса StrVecвлечет за собой копирование каждой строки из прежнего объекта StrVecв новый. Даже без подробностей реализации класса stringизвестно, что строки ведут себя подобно значению. После копирования новая строка и оригинальная независимы друг от друга. Изменения, внесенные в оригинал, не распространяются на копию, и наоборот.
Поскольку строки действуют, как значения, можно сделать вывод, что у каждой строки должна быть собственная копия составляющих ее символов. Копирование строки должно резервировать память для этих символов, а удаление строки должно освободить используемую ею память.
Копирование строки подразумевает копирование данных, поскольку обычно после копирования строки у нее будет два пользователя. Но когда функция reallocate()копирует строки объекта класса StrVec, у этих строк будет только один пользователь. Как только копирование элементов из прежнего пространства в новое завершается, исходные строки немедленно удаляются.
Копирование данных этих строк не нужно. Производительность класса StrVecбудет значительно выше , если удастся избежать дополнительных затрат на резервирование и освобождение строк при каждом его пересоздании.
Конструктор перемещения и функция std::move()Копирования строки можно избежать при помощи двух средств, введенных новой библиотекой. Во-первых, некоторые из библиотечных классов, включая класс string, определяют так называемые конструкторы перемещения (move constructor). Подробности работы конструктора перемещения класса string(равно как и все остальные подробности его реализации) не раскрываются. Однако общеизвестно, что конструкторы перемещения обычно "перемещают" ресурсы из заданного объекта в создаваемый. Библиотека гарантирует также то, что "перемещенная" строка останется в допустимом состоянии. В случае класса stringможно предположить, что у каждого его объекта есть указатель на массив типа char. По-видимому, конструктор перемещения класса stringкопирует указатель вместо резервирования нового пространства и копирования символов.
Второе доступное для использования средство — это библиотечная функция move(), определенная в заголовке utility. Есть два важных момента, которые следует знать о функции move(). Во-первых, по причинам, рассматриваемым в разделе 13.6.1, когда функция reallocate()создает строки в новой области памяти, она должна вызвать функцию move(), чтобы сообщить о необходимости использования конструктора перемещения класса string. Если пропустить вызов функции move(), то будет использован конструктор копий класса string. Во-вторых, по причинам, рассматриваемым в разделе 18.2.3, объявление using(см. раздел 3.1) для функции move()обычно не предоставляется. Когда используется функция move(), вызывается функция std::move(), а не move().
Интервал:
Закладка: