Скотт Мейерс - Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14
- Название:Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:2016
- Город:Москва
- ISBN:978-5-8459-2000-3
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Скотт Мейерс - Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 краткое содержание
В книге рассматриваются следующие темы. Освоение С++11 и С++14 — это больше, чем просто ознакомление с вводимыми этими стандартами возможностями (например, объявлениями типов
, семантикой перемещения, лямбда-выражениями или поддержкой многопоточности). Вопрос в том, как использовать их эффективно, чтобы создаваемые программы были корректны, эффективны и переносимы, а также чтобы их легко можно было сопровождать. Именно этим вопросам и посвящена данная книга, описывающая создание по-настоящему хорошего программного обеспечения с использованием C++11 и С++14 — т.е. с использованием современного С++.
■ Преимущества и недостатки инициализации с помощью фигурных скобок, спецификации
, прямой передачи и функций
интеллектуальных указателей
■ Связь между
,
, rvalue-ссылками и универсальными ссылками
■ Методы написания понятных, корректных,
лямбда-выражений
■ Чем
отличается от
, как они используются и как соотносятся с API параллельных вычислений С++
■ Какие из лучших методов “старого” программирования на С++ (т.е. С++98) должны быть пересмотрены при работе с современным С++
Более чем 20 лет книги
серии
являются критерием уровня книг по программированию на С++. Понятное пояснение сложного технического материала принесло ему всемирную известность. Он всегда самый желанный гость на международных конференциях, а его услуги консультанта широко востребованы во всем мире.
Скотт Мейерс Эффективный и современный С++, После изучения основ С++ я перешел к изучению того, как применять С++ в промышленном программировании, с помощью серии книг Скотта Мейерса Эффективный С++. Эффективный и современный С++ — наиболее важная из книг серии, предлагающая ключевые рекомендации, стили и идиомы, позволяющие эффективно использовать современный С++. Вы еще не купили эту книгу? Сделайте это прямо сейчас. Герб Саттер,
глава Комитета ISO по стандартизации С++, специалист в области архитектуры программного обеспечения на С++ в Microsoft
Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
using ProcessFuncType = // Псевдоним типа (раздел 3.3)
int (*)(int);
ProcessFuncTypeprocessValPtr = // Определяем необходимую
processVal; // сигнатуру processVal
fwd(processValPtr); // OK
fwd( static_cast(workOnVal)); // Также OK
Конечно, это требует знания типа указателя на функцию, передаваемого шаблоном fwd
. Разумно предположить, что функция с прямой передачей это документирует. В конце концов, функции с прямой передачей предназначены для принятия всего что угодно, так что если нет никакой документации, говорящей, что должно быть передано, то откуда вы узнаете, что им передавать?
Последний случай неудачной прямой передачи — когда в качестве аргумента функции используется битовое поле. Чтобы увидеть, что это означает на практике, рассмотрим заголовок IPv4, который может быть смоделирован следующим образом: [19] Здесь предполагается, что битовые поля располагаются от младшего бита к старшему. С++ это не гарантирует, но компиляторы часто предлагают механизм, который позволяет программисту управлять схемой размещения битовых полей.
struct IPv4Header {
std::uint32_t version: 4,
IHL: 4,
DSCP: 6,
ECN: 2,
totalLength: 16;
};
Если наша многострадальная функция f
(являющаяся целевой для нашей функции прямой передачи fwd
) объявлена как принимающая параметр std::size_t
, то вызов, скажем, с полем totalLength
объекта IPv4Header компилируется без проблем:
void f(std::size_t sz); // Вызываемая функция
IPv4Header h;
…
f(h.totalLength); // Все в порядке
Однако попытка передать h.totalLength
в f
через fwd
— это совсем другая история:
fwd(h.totalLength); // Ошибка!
Проблема заключается в том, что параметр функции fwd
представляет собой ссылку, а h.totalLength
— неконстантное битовое поле. Это может показаться не столь уж плохим, но стандарт С++ осуждает это сочетание в непривычно ясной форме: “неконстантная ссылка не может быть привязана к битовому полю”. Тому есть превосходная причина. Битовые поля могут состоять из произвольных частей машинных слов (например, биты 3-5 из 32-битного int
), но непосредственно их адресовать нет никакой возможности. Ранее я упоминал, что ссылки и указатели представляют собой одно и то же на аппаратном уровне, и просто так же, как нет никакого способа создать указатели на отдельные биты (С++ утверждает, что наименьшей сущностью, которую вы можете адресовать, является char
), нет никакого способа связать ссылку с произвольными битами.
Обходной путь для невозможности прямой передачи битовых полей становится простым, как только вы осознаете, что любая функция, принимающая битовое поле в качестве аргумента, на самом деле получает копию значения битового поля. В конце концов, никакая функция не может привязать ссылку к битовому полю, поскольку не существует указателей на битовые поля. Единственная разновидность параметров, которым могут передаваться битовые поля, — это параметры, передаваемые по значению, и, что интересно, ссылки на const
. В случае передачи по значению вызываемая функция, очевидно, получает копию значения в битовом поле, и оказывается, что в случае параметра, являющегося ссылкой на const
, стандарт требует, чтобы эта ссылка в действительности была привязана к копии значения битового поля, сохраненного в объекте некоторого стандартного целочисленного типа (например, int
). Ссылки на const
не привязываются к битовым полям, они привязываются к “нормальным” объектам, в которые копируются значения битовых полей.
Итак, ключом к передаче битового поля в функцию с прямой передачей является использование того факта, что функция, в которую осуществляется передача, всегда получает копию значения битового поля. Таким образом, вы можете сделать копию самостоятельно и вызвать передающую функцию, передав ей копию. В нашем примере с IPv4Header
код, осуществляющий этот подход, имеет следующий вид:
// Копирование значения битового поля; см. раздел 2.2
auto length = static_cast(h.totalLength);
fwd(length); // Передача копии
В большинстве случаев прямая передача работает так, как разрекламировано. Вы редко должны задумываться о ней. Но когда она не работает (разумно выглядящий код не компилируется или, хуже того, компилируется, но работает не так, как вы ожидаете), важно знать о несовершенствах прямой передачи. Не менее важно знать, как эти несовершенства обойти. В большинстве случаев это довольно просто.
• Прямая передача неудачна, когда вывод типа не удается выполнить или когда он выводит неверный тип.
• Разновидностями аргументов, которые приводят к неудачам при прямой передаче, являются инициализаторы в фигурных скобках, нулевые указатели, выраженные как 0
или NULL
, целочисленные члены-данные, объявленные как const static
и не имеющие определений, имена шаблонов и перегруженных функций и битовые поля.
Глава 6
Лямбда-выражения
Лямбда-выражения, иногда называемые просто лямбдами (lambdas), существенно изменили правила игры в программировании на С++. Это несколько удивительно, так как они не внесли в язык никаких новых возможностей выражения идей. Все, на что способны лямбда-выражения, вы в состоянии сделать вручную, разве что ценой немного больших усилий по вводу с клавиатуры. Но лямбда-выражения представляют собой очень удобное средство создания функциональных объектов, оказывающее огромное влияние на повседневную разработку программного обеспечения на С++. Без лямбда-выражений алгоритмы “ _if
” из STL (например, std::find_if
, std::remove_if
, std::count_if
и др.) обычно работают с самыми тривиальными предикатами, но при доступности лямбда-выражений применение этих алгоритмов резко возрастает. То же самое верно и для алгоритмов, настраиваемых с помощью пользовательской функции сравнения (например, std::sort
, std::nth_element
, std::lower_bound
и др.). Вне STL лямбда-выражения позволяют быстро создавать пользовательские удалители для std::unique_ptr
и std::shared_ptr
(см. разделы 4.1 и 4.2) и делают столь же простыми спецификации предикатов для переменных условий в потоковом API (см. раздел 7.5). Помимо использования в объектах стандартной библиотеки, лямбда-выражения облегчают определение функций обратного вызова “на лету”, функций адаптации интерфейса и контекстно-зависимых функций для разовых вызовов. Лямбда-выражения действительно делают С++ более приятным языком программирования.
Терминология, связанная с лямбда-выражениями, может обескуражить. Лямбда-выражение является именно тем, что написано: выражением. Это часть исходного текста. В приведенном ниже фрагменте выделенная полужирным шрифтом часть представляет собой лямбда-выражение.
Читать дальшеИнтервал:
Закладка: