Скотт Мейерс - Эффективный и современный С++. 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
не может быть модифицировано, не означает, что таковой должна быть и его копия.
Интервал:
Закладка: