Скотт Мейерс - Эффективный и современный С++. 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 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Следовательно, нам надо рассмотреть три сценария вывода. Каждый из них основан на нашем общем виде шаблонов и их вызова:
templateТ>
void f( ParamType param);
f( expr ); // Вывод Т и ParamType из expr
ParamType является указателем или ссылкой, но не универсальной ссылкойПростейшая ситуация — когда ParamTypeявляется ссылочным типом или типом указателя, но не универсальной ссылкой. В этом случае вывод типа работает следующим образом.
1. Если типом exprявляется ссылка, ссылочная часть игнорируется.
2. Затем выполняется сопоставление типа exprс ParamTypeдля определения Т. Например, если у нас имеются шаблон
template
void f( T¶m); // param представляет собой ссылку
и объявления переменных
int x = 27; // x имеет тип int
const int cx = x; // cx имеет тип const int
const int& rx = x; // rx является ссылкой на x как на const int
то выводимые типы для paramи Тв различных выводах будут следующими:
f(x); // Т - int, тип param - int&
f(cx); // Т - const int, тип param - const int&
f(rx); // Т - const int, тип param - const int&
Во втором и третьем вызовах обратите внимание, что, поскольку cxи rxобъявлены как константные значения, Твыводится как const intтем самым приводя к типу параметра const int&. Это важно для вызывающего кода. Передавая константный объект параметру-ссылке, он ожидает, что объект останется неизменным, т.е. что параметр будет представлять собой ссылку на const. Вот почему передача константного объекта в шаблон, получающий параметр T&, безопасна: константность объекта становится частью выведенного для Ттипа.
В третьем примере обратите внимание, что несмотря на то, что типом rxявляется ссылка, тип Tвыводится как не ссылочный. Вот почему при выводе типа игнорируется “ссылочность” rx.
Все эти примеры показывают ссылочные параметры, являющиеся lvalue, но вывод типа точно так же работает и для ссылочных параметров rvalue. Конечно, аргументы могут передаваться только ссылочным параметрам, являющимся rvalue, но это ограничение никак не влияет на вывод типов.
Если мы изменим тип параметра fс Т&на const Т&, произойдут небольшие изменения, но ничего удивительного не случится. Константность cxи rxпродолжает соблюдаться, но поскольку теперь мы считаем, что paramявляется ссылкой на const, constкак часть выводимого типа Tне требуется:
template
void f( const T¶m); // param является ссылкой на const
int x = 27; // Как и ранее
const int cx = x; // Как и ранее
const int& rx = x; // Как и ранее
f(x); // Т - int, тип param - const int&
f(cx); // Т - int, тип param - const int&
f(rx); // Т - int, тип param - const int&
Как и ранее, “ссылочность” rxпри выводе типа игнорируется.
Если бы paramбыл указателем (или указателем на const), а не ссылкой, все бы работало, по сути, точно так же:
template
void f( T*param); // Теперь param является указателем
int x = 27; // Как и ранее
const int *px = &x; // px - указатель на x, как на const int
f(&x); // Т - int, тип param - int*
f(px); // Т - const int, тип param - const int*
Сейчас вы можете обнаружить, что давно усердно зеваете, потому что все это очень скучно, правила вывода типов в С++ работают так естественно для ссылок и указателей, что все просто очевидно! Это именно то, что вы хотите от системы вывода типов.
ParamType является универсальной ссылкойВсе становится менее очевидным в случае шаблонов, принимающих параметры, являющиеся универсальными ссылками. Такие параметры объявляются как ссылки rvalue (т.е. в шаблоне функции, принимающем параметр типа Т, объявленным типом универсальной ссылки является Т&&), но ведут себя иначе при передаче аргументов, являющихся lvalue. Полностью вопрос рассматривается в разделе 5.2, здесь приводится его сокращенная версия.
• Если exprпредставляет собой lvalue, как Т, так и ParamTypeвыводятся как lvalue-ссылки. Это вдвойне необычно. Во-первых, это единственная ситуация в выводе типа шаблона, когда Т выводится как ссылка. Во-вторых, хотя ParamTypeобъявлен с использованием синтаксиса rvalue-ссылки, его выводимым типом является lvalue-ссылка.
• Если exprпредставляет собой rvalue, применяются “обычные” правила (из случая 1). Примеры
template
void f( T&¶m); // param является универсальной ссылкой
int x = 27; // Как и ранее
const int cx = x; // Как и ранее
const int& rx = x; // Как и ранее
f(x); // x - lvalue, так что Т - int&,
// тип param также является int&
f(cx); // cx - lvalue, так что Т - const int&,
// тип param также является const int&
f(rx); // rx - lvalue, так что Т - const int&,
// тип param также является const int&
f(27); // 27 - rvalue, так что Т - int,
// следовательно, тип param - int&&
В разделе 5.2 поясняется, почему эти примеры работают именно так, а не иначе. Ключевым моментом является то, что правила вывода типов для параметров, являющихся универсальными ссылками, отличаются от таковых для параметров, являющихся lvalue- или rvalue-ссылками. В частности, когда используются универсальные ссылки, вывод типов различает аргументы, являющиеся lvalue, и аргументы, являющиеся rvalue. Этого никогда не происходит для неуниверсальных ссылок.
ParamType не является ни указателем, ни ссылкойКогда ParamTypeне является ни указателем, ни ссылкой, мы имеем дело с передачей по значению:
template
void f( Tparam); // param передается по значению
Это означает, что paramбудет копией переданного функции — совершенно новым объектом. Тот факт, что paramбудет совершенно новым объектом, приводит к правилам, которые регулируют вывод Тиз expr.
1. Как и ранее, если типом exprявляется ссылка, ссылочная часть игнорируется.
2. Если после отбрасывания ссылочной части exprявляется const, это также игнорируется. Игнорируется и модификатор volatile(объекты volatileявляются редкостью и в общем случае используются только при реализации драйверов устройств; детальную информацию на эту тему вы найдете в разделе 7.6.)
Таким образом, получаем следующее:
int x = 27; // Как и ранее
const int cx = x; // Как и ранее
const int& rx = x; // Как и ранее
f(x); // Типами и Т, и param являются int
f(cx); // Типами и Т, и param вновь являются int
f(rx); // Типами и Т, и param опять являются int
Обратите внимание, что даже несмотря на то, что cxи rxпредставляют константные значения, paramне является const. Это имеет смысл. paramпредставляет собой объект, который полностью независим от cxи rx, — это копия cxили rx. Тот факт, что cxи rxне могут быть модифицированы, ничего не говорит о том, может ли быть модифицирован param. Вот почему константность expr(как и volatile, если таковой модификатор присутствует) игнорируется при выводе типа param: то, что exprне может быть модифицировано, не означает, что таковой должна быть и его копия.
Интервал:
Закладка: