Стенли Липпман - Язык программирования 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()
с символьными указателями, будет вызвана первая версия шаблона:
Интервал:
Закладка: