Скотт Мейерс - Эффективный и современный С++. 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 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
return std::forward(c )[i];
}
Этот код должен делать все, что мы хотели, но он требует компилятора С++14. Если у вас нет такового, вам следует использовать версию шаблона для С++11. Она такая же, как и ее аналог С++14, за исключением того, что вы должны самостоятельно указать возвращаемый тип:
template // Окончательная
auto // версия для
authAndAccess(Container&& с, Index i) // C++11
-> decltype(std::forward(с)[i]){
authenticateUser();
return std::forward(с)[i]);
}
Вторым беспокоящим моментом является мое замечание в начале этого раздела о том, что decltype
почти всегда дает тип, который вы ожидаете, т.е. что он редко преподносит сюрпризы. По правде говоря, вряд ли вы столкнетесь с этими исключениями из правила, если только вы не занимаетесь круглосуточно написанием библиотек.
Чтобы полностью понимать поведение decltype
, вы должны познакомиться с некоторыми особыми случаями. Большинство из них слишком невразумительны, чтобы быть размещенными в этой книге, но один из них приводит к лучшему пониманию decltype
и его применения.
Применение decltype
к имени дает объявленный тип для этого имени. Имена представляют собой lvalue-выражения, но это не влияет на поведение decltype
. Однако для lvalue-выражений, более сложных, чем имена, decltype
гарантирует, что возвращаемый тип всегда будет lvalue-ссылкой. Иначе говоря, если lvalue-выражение, отличное от имени, имеет тип Т
, то decltype
сообщает об этом типе как об Т&
. Это редко на что-то влияет, поскольку тип большинства lvalue-выражений в обязательном порядке включает квалификатор lvalue-ссылки. Например, функции, возвращающие lvalue, всегда возвращают lvalue-ссылки.
Однако у этого поведения есть следствия, о которых необходимо знать. В коде
int x = 0;
x
является именем переменной, так что decltype(x)
представляет собой int
. Однако “заворачивание” имени x
в скобки — “ (x)
” — дает выражение, более сложное, чем имя. Будучи именем, x
представляет собой lvalue, и С++ также определяет выражение (x)
как lvalue. Следовательно, decltype((x))
представляет собой int&
. Добавление скобок вокруг имени может изменить тип, возвращаемый для него decltype
!
В C++11 это просто любопытный факт, но в сочетании с поддержкой в С++14 decltype (auto)
это означает, что, казалось бы, тривиальные изменения в способе записи инструкции return
могут повлиять на выводимый тип функции:
decltype(auto)f1() {
int x = 0;
…
return x; // decltype(x) представляет собой int,
} // так что f1 возвращает int
decltype(auto)f2() {
int x = 0;
…
return (x); // decltype((x)) представляет собой int&,
} // так что f2 возвращает int&
Обратите внимание, что f2
не только имеет возвращаемый тип, отличный от f1
, но и возвращает ссылку на локальную переменную! Этот код ведет вас к неопределенному поведению, что вряд ли является вашей целью.
Основной урок состоит в том, чтобы при использовании decltype(auto)
уделять деталям самое пристальное внимание. Кажущиеся совершенно незначительными детали в выражении, для которого выводится тип, могут существенно повлиять на тип, возвращаемый decltype(auto)
. Чтобы гарантировать, что выводимый тип — именно тот, который вы ожидаете, используйте методы, описанные в разделе 1.4.
В то же время не забывайте и о более широкой перспективе. Конечно, decltype
(как автономный, так и в сочетании с auto
) при выводе типов иногда может привести к сюрпризам, но это не нормальная ситуация. Как правило, decltype
возвращает тот тип, который вы ожидаете. Это особенно верно, когда decltype
применяется к именам, потому что в этом случае decltype
делает именно то, что скрывается в его названии: сообщает объявленный тип ( decl ared type ) имени.
• decltype
почти всегда дает тип переменной или выражения без каких-либо изменений.
• Для lvalue-выражений типа Т
, отличных от имени, decltype
всегда дает тип T&
.
• C++14 поддерживает конструкцию decltype(auto)
, которая, подобно auto
, выводит тип из его инициализатора, но выполняет вывод типа с использованием правил decltype
.
1.4. Как просмотреть выведенные типы
Выбор инструментов для просмотра результатов вывода типа зависит от фазы процесса разработки программного обеспечения, на которой вы хотите получить эту информацию. Мы рассмотрим три возможности: получение информации о выводе типа при редактировании кода, во время компиляции и во время выполнения.
Редакторы исходных текстов в IDE часто показывают типы программных сущностей (например, переменных, параметров, функций и т.п.), когда вы, например, помещаете указатель мыши над ними. Например, пусть у вас есть код
const int theAnswer = 42;
auto x= theAnswer;
auto y= &theAnswer;
Редактор, скорее всего, покажет, что выведенный тип x
представляет собой int
, а выведенный тип y
— const int*
.
Чтобы это сработало, ваш код должен быть в более-менее компилируемом состоянии, поскольку такого рода информация поставляется среде разработки компилятором С++ (или как минимум его клиентской частью), работающим в IDE. Если компилятор не в состоянии получить достаточно информации о вашем коде, чтобы выполнить вывод типа, вы не сможете увидеть выведенные типы.
Для простых типов наподобие int
информация из IDE в общем случае вполне точна. Однако, как вы вскоре увидите, когда приходится иметь дело с более сложными типами, информация, выводимая IDE, может оказаться не особенно полезной.
Эффективный способ заставить компилятор показать выведенный тип — использовать данный тип так, чтобы это привело к проблемам компиляции. Сообщение об ошибке практически обязательно будет содержать тип, который к ней привел.
Предположим, например, что мы хотели бы узнать типы, выведенные для x
и y
из предыдущего примера. Сначала мы объявляем шаблон класса, но не определяем его. Чего- то такого вполне хватит:
template // Только объявление TD;
class TD;
Попытки инстанцировать этот шаблон приведут к сообщению об ошибке, поскольку инстанцируемый шаблон отсутствует. Чтобы увидеть типы x
и y
, просто попробуйте инстанцировать TD с их типами:
TD xType; // Сообщение об ошибке будет
TD yType; // содержать типы x и y
Я использую имена переменных вида variableNameType
, чтобы проще найти интересующую меня информацию в сообщении об ошибке. Мой компилятор для приведенного выше кода сообщает, в частности, следующее (я выделил интересующую меня информацию о типах):
Интервал:
Закладка: