Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
16.4.3. Перенаправление пакетов параметров
По новому стандарту можно использовать шаблоны с переменным количеством аргументов совместно с функцией forward()для написания функций, которые передают свои аргументы неизменными некой другой функции. Чтобы проиллюстрировать такие функции, добавим в класс StrVec(см. раздел 13.5) функцию-член emplace_back(). Такая функция-член библиотечных контейнеров является шаблоном-членом с переменным количеством аргументов (см. раздел 16.1.4), которая использует их для создания элементов непосредственно в области, управляемой контейнером.
Версия функции emplace_back()для класса StrVecтакже должна быть с переменным количеством аргументов, поскольку у класса stringмного конструкторов, которые отличаются своими параметрами.
Поскольку желательно быть в состоянии использовать конструктор перемещения класса string, необходимо будет также сохранять всю информацию о типах аргументов, переданных функции emplace_back().
Как уже упоминалось, сохранение информации типа — двухступенчатый процесс. Во-первых, для сохранения информации типа аргументов параметры функции emplace_back()следует определить как ссылки на r-значение параметра типа шаблона (см. раздел 16.2.7):
class StrVec {
public:
template void emplace_back(Args&&...);
// остальные члены, как в разделе 13.5
};
Схема &&в развертывании пакета параметров шаблона означает, что каждый параметр функции будет ссылкой на r-значение на соответствующий ей аргумент.
Во-вторых, функцию forward()следует использовать для сохранения первоначальных типов аргументов, когда функция emplace_back()передает их функции construct()(см. раздел 16.2.7):
template
inline
void StrVec::emplace_back(Args&&... args) {
chk_n_alloc(); // пересоздает StrVec при необходимости
alloc.construct(first_free++, std::forward(args)...);
}
Тело функции emplace_back()вызывает функцию chk_n_alloc()(см. раздел 13.5), чтобы гарантировать наличие достаточного места для элемента, и вызывает функцию construct(), чтобы создать элемент в позиции, на которую указывает указатель first_free.
std::forward(args)...
Развертывание в вызове функции construct()разворачивает оба пакета: параметров шаблона Argsи параметров функции args. Эта схема создает элементы в формате:
std::forward< T i >( t i )
где T i представляет тип i -го элемента в пакете параметров шаблона, a t i представляет i -й элемент в пакете параметров функции. Например, если svecимеет тип StrVec, то при вызове
svec.emplace_back(10, 'c'); // добавит cccccccccc как новый последний
// элемент
схема в вызове функции construct()развернется в
std::forward(10), std::forward(c)
Использование функции forward()в этом вызове гарантирует, что если функция emplace_back()будет вызвана с r-значением, то функция construct()также получит r-значение. Например, в вызове
svec.emplace_back(s1 + s2); // использует конструктор перемещения
аргумент функции emplace_back()является r-значением, которое передается функции construct()как
std::forward(string("the end"))
Типом результата вызова forwardбудет strings&, поэтому функция construct()будет вызвана со ссылкой на r-значение. Функция construct(), в свою очередь, перенаправит этот аргумент конструктору перемещения класса string, чтобы создать этот элемент.
Функции с переменным количеством аргументов зачастую перенаправляют свои параметры другим функциям. Форма таких функций, как правило, подобна функции emplace_back():
// у функции fun() может быть любое количество параметров, каждый
// из которых является ссылкой r-значения на тип параметра шаблона
template
void fun(Args&&... args) // развертывание Args в список ссылок
// на r-значения
{
// аргумент work() развертывает как Args, так и args
work(std::forward(args)...);
}
Здесь предполагается перенаправить все аргументы функции fun()другой функции, work(), которая, по-видимому, осуществляет реальную работу. Как и вызов функции construct()в функции emplace_back(), развертывание в вызове функции work()разворачивает и пакет параметров шаблона, и пакет параметров функции.
Поскольку параметры функции fun()являются ссылками на r-значение, функции fun()можно передать аргументы любого типа; поскольку для передачи этих аргументов используется функция std::forward(), вся информация о типах этих аргументов будет сохраняться в вызове функции work().
Упражнение 16.58. Напишите функцию emplace_back()для собственного класса StrVecи для класса Vec, написанного в упражнении раздела 16.1.2.
Упражнение 16.59. С учетом того, что sимеет тип string, объясните вызов svec.emplace_back(s).
Упражнение 16.60. Объясните, как работает функция make_shared()(см. раздел 12.1.1).
Упражнение 16.61. Определите собственную версию функции make_shared().
16.5. Специализация шаблона
Не всегда можно написать один шаблон, который наилучшим образом подходит для всех возможных типов аргументов шаблона, для которых может быть создан его экземпляр. В некоторых случаях общий шаблон просто не подходит для типа: он либо приводит к ошибке при компиляции, либо к неправильным действиям. С другой стороны, иногда можно воспользоваться уникальными возможностями определенного типа для создания более эффективной функции, чем та, которой снабжен экземпляр общего шаблона.
Функция compare()— хороший пример шаблона функции, общее определение которого не подходит для специфического типа, а именно символьных указателей. Хотелось бы, чтобы функция compare()сравнивала символьные указатели, используя функцию strcmp(), а не сравнивала значения указателей. Действительно, ведь уже есть перегруженная функция compare(), обрабатывающая символьные строковые литералы (см. раздел 16.1.1):
// первая версия; может сравнить любые два типа
template int compare(const T&, const T&);
// вторая версия, для обработки строковых литералов
template
int compare(const char (&)[N], const char (&)[M]);
Однако версия функции compare()с двумя параметрами значения шаблона будет вызвана только при передаче строкового литерала или массива. Если происходит вызов функции compare()с символьными указателями, будет вызвана первая версия шаблона:
Интервал:
Закладка: