Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 [заметки]

Шрифт
Интервал

1

Русский перевод — Александреску Андрей. Современное проектирование на С++. — М.: Издательский дом “Вильямс”, 2002.

2

Возможен и более гибкий дизайн, который позволяет вызывающим функциям определить, должны ли использоваться круглые или фигурные скобки в функциях, генерируемых из шаблонов. Подробности можно найти в записи от 5 июня 2013 года в Andrzej's С++ blog, “Intuitive interface — Part I”.

3

Синдром запястного канала — неврологическое заболевание, проявляющееся длительной болью и онемением пальцев рук. Широко распространено представление, что длительная ежедневная работа на компьютере, требующая постоянного использования клавиатуры, является фактором риска развития синдрома запястного канала. — Примеч. пер.

4

Применение ключевого слова >final к виртуальной функции препятствует перекрытию этой функции в производном классе. Ключевое слово >final также может быть применено к классу; в этом случае класс становится неприменимым в качестве базового.

5

“As if rule” — правило, согласно которому разрешены любые преобразования кода, не изменяющие наблюдаемое поведение программы. — Примеч. ред.

6

Обычно в русскоязычной литературе для термина stack unwinding используется перевод “разворачивание стека”. Однако это не совсем верный перевод. Вот что в переписке с редактором книги пишет по этому поводу профессор университета Иннополис E. Зуев: “Самый частый вариант перевода — «раскрутка стека» — не просто затемняет существо дела, но просто-таки противоположен ему. При срабатывании исключения начинается процесс поиска в стеке секции (“кадра стека”, stack frame), для которой задан перехват случившегося исключения. В тексте исходной программы такой секции соответствует try-блок с catch-обработчиком, в котором задано имя случившегося исключения. И в процессе этого поиска все секции стека, для которых такой перехват не задан, из стека удаляются. Говорят еще, что производится поиск секции по всей динамической цепочке вызовов. Тем самым стек в целом сокращается, сворачивается. Таким образом, самый адекватный вариант перевода — сворачивание стека”. Поэтому принято решение переводить stack unwinding как сворачивание стека. — Примеч. ред.

7

Проверка обычно выполняется окольным путем. Функции наподобие >std::vector::push_back вызывают шаблон >std::move_if_noexcept, вариацию шаблона >std::move, который условно выполняет приведение к rvalue (см. раздел 5.1), в зависимости от того, объявлен ли перемещающий конструктор как >noexcept. В свою очередь, >std::move_if_noexcept консультируется с >std::is_nothrow_move_constructible, а значение этого свойства типа (см. раздел 3.3) устанавливается компиляторами в зависимости от того, объявлен ли перемещающий конструктор как >noexcept (или >throw()).

8

В спецификациях интерфейса для операций перемещения в контейнерах стандартной библиотеки >noexcept отсутствует. Однако разработчикам разрешено усиливать спецификации интерфейсов функций стандартной библиотеки, и на практике как минимум для некоторых контейнеров операции перемещения объявляются как >noexcept. Эта практика является примером следования совету из данного раздела. Обнаружив, что можно написать операции перемещения так, что исключения гарантированно не будут генерироваться, разработчики часто объявляют такие операции как >noexcept, несмотря на то что стандарт языка от них этого не требует.

9

“Независимо от состояния программы” и “без ограничений” не узаконивает программы, поведение которых уже является неопределенным. Например, >std::vector::size имеет широкий контракт, но это не означает, что данная функция должна разумно себя вести при применении к произвольному блоку памяти, приведенному к типу >std::vector. Результат приведения не определен, поэтому нет никаких гарантий, касающихся поведения программы, содержащей такое приведение.

10

Поскольку P>oint::xValue возвращает >double, типом >mid.xValue() * 10 также является >double. Типы с плавающей точкой не могут использоваться для инстанцирования шаблонов или для указания значений перечислений, но они могут быть использованы как части больших выражений, дающих интегральные типы. Например, для инстанцирования шаблона или для указания значения перечислителя может использоваться выражение >static_cast(mid.xValue() * 10).

11

Из этого правила есть несколько исключений. Большинство из них обусловлено аварийным завершением программы. Если исключение выходит за пределы основной функции потока (например, >main в случае начального потока программы) или если нарушена спецификация >noexcept (см. раздел 3.8), локальные объекты могут не быть уничтожены; они, определенно, не уничтожаются, когда вызывается функция >std::abort или функция выхода (т.e. >std::_Exit, >std::exit или >std::quick_exit).

12

Стандарт не требует использования именно такой реализации, но все известные мне реализации стандартной библиотеки поступают именно так

13

Дня создания полнофункциональной версии >make_unique с минимальными усилиями поищите документ, ставший ее источником, и скопируйте из него ее реализацию. Этот документ — N3656 от 18 апреля 2013 года, его автор — Стивен T. Лававей (Stephan T. Lavavej).

14

На практике значение слабого счетчика не всегда совпадает с количеством указателей >std::weak_ptr, ссылающихся на управляющий блок, поскольку разработчики библиотеки нашли способы добавлять в слабый счетчик дополнительную информацию, которая упрощает генерацию лучшего кода. В данном разделе мы игнорируем этот факт и считаем, что значение слабого счетчика представляет собой количество указателей >std::weak_ptr, ссылающихся на управляющий блок.)).

15

Непереводимая игра слов, основанная на использовании для обычного указателя названия “raw pointer” (дословно — “сырой указатель”). — Примеч. пер.

16

В разделе 5.3 поясняется, что к универсальным ссылкам почти всегда может применяться >std::forward, так что, когда эта книга готовилась к печати, некоторые члены сообщества С++ начинали именовать универсальные ссылки передаваемыми ссылками.

17

Такими локальными объектами являются большинство локальных переменных (например, такие как >w в >makeWidget), а также временные объекты, создаваемые как часть инструкции >return. Параметры функции на такое звание претендовать нс могут. Некоторые программисты различают применение RVO к именованным и неименованным (т.e. временным) локальным объектам, ограничивая термин “RVO” неименованными объектами и называя его применение к именованным объектам оптимизацией именованных возвращаемых значений (named return value optimization — NRVO).

18

Известная история о том, что об одном и том же до средины наполненном стакане пессимисты говорят, что он наполовину пуст, а оптимисты — что он наполовину полон. — Примеч. пер.

19

Здесь предполагается, что битовые поля располагаются от младшего бита к старшему. С++ это не гарантирует, но компиляторы часто предлагают механизм, который позволяет программисту управлять схемой размещения битовых полей.

20

>std::bind всегда копирует свои аргументы, но вызывающий код может добиться эффекта сохранения аргумента по ссылке путем применения >std::ref. Результат вызова

>auto compressRateB = std::bind(compress, std::ref(w), _1);

состоит в том. что >compressRateB действует так, как если бы сохранялась ссылка на объект >w, а не его копия.

21

В предположении, что таковая имеется. В некоторых встроенных системах ее нет.

22

Это упрощение. Значение имеет не фьючерс, для которого вызывается >get или >wait, а совместно используемое состояние, на которое ссылается фьючерс. (В разделе 7.4 обсуждается взаимосвязь фьючерсов и совместно используемых состояний.) Поскольку >std: future поддерживают перемещение, а также могут использоваться для построения >std::shared_future и поскольку >std::shared_future могут копироваться, объект фьючерса, ссылающийся на совместно используемое состояние, возникающее из вызова >std::async, в который была передана >f, вероятно, будет отличаться от фьючерса, возвращенного >std::async. Однако обычно просто говорят о вызове функций-членов >get или >wait фьючерса, возвращенного из >std::async.

23

Часто их переводят как объединяемое и необъединяемое, но, на наш взгляд, термин подключение лучше отражает смысл происходящего с потоком, связанным с объектом >std::thread, при вызове функции >join, как и отключение для происходящего при вызове функции >detach. — Примеч. пер.

24

Вы можете обратиться к книге Энтони Вильямса (Anthony Williams) С++ Concurrency in Action (Manning Publications, 2012), раздел 9.2.

25

В разделе 7.5 поясняется, что разновидность канала связи фьючерса может быть использована и для других целей. Однако в этом разделе мы будем рассматривать только его применение в качестве механизма для передачи результата из вызываемой функции вызывающей.

26

Разумной отправной точкой для начала изучения этого вопроса является запись в моем блоге от 24 декабря 2013 года в The View From Aristeia, “ThreadRAII + Thread Suspension = Trouble?”

27

Это справедливо только для >std::аtomic, использующих последовательную согласованность, которая является применяемой по умолчанию (и единственной) моделью согласованности дня объектов >std::atomic, использующих показанный в этой книге синтаксис. C++11 поддерживает также модели согласованности с более гибкими правилами переупорядочения кода. Такие слабые (или смягченные) модели делают возможным создание программного обеспечения, работающего более быстро на некоторых аппаратных архитектурах, но применение таких моделей дает программное обеспечение, которое гораздо труднее правильно понимать и поддерживать. Тонкие ошибки в коде с ослабленной атомарностью не являются редкостью даже для экспертов, так что вы должны придерживаться, насколько это возможно, последовательной согласованности.

28

Тип >y получается с помощью вывода >auto, так что используются правила, описанные в разделе 1.2. Эти правила предписывают, чтобы для объявления типов, не являющихся ссылочными или типами указателей (что и выполняется о случае >y), квалификаторы >const и >volatile были опущены. Следовательно, типом >y является просто >int. Это означает, что избыточные чтения и записи >y могут быть удалены. В приведенном примере компиляторы должны выполнять и инициализацию, и присваивание >y, поскольку >x объявлена как >volatile, так что второе чтение >x может давать другое значение, отличное от первого.

29

В данном разделе “копирование” параметра в общем случае означает его использование как источника для операций копирования или перемещения. Помните, что в С++ нет терминологического различия между копированием, выполняемым с помощью операции копирования, и копированием с помощью операции перемещения.

30

Для таких предложений хорошо бы иметь терминологию, отличающую копирование с помощью копирующего конструктора от копирования с помощью перемещающего конструктора.


Еще от автора Скотт Мейерс
Эффективное использование STL

В этой книге известный автор Скотт Мейерс раскрывает секреты настоящих мастеров, позволяющие добиться максимальной эффективности при работе с библиотекой STL.Во многих книгах описываются возможности STL, но только в этой рассказано о том, как работать с этой библиотекой. Каждый из 50 советов книги подкреплен анализом и убедительными примерами, поэтому читатель не только узнает, как решать ту или иную задачу, но и когда следует выбирать то или иное решение — и почему именно такое.


Как функции, не являющиеся методами, улучшают инкапсуляцию

Когда приходится инкапсулировать, то иногда лучше меньше, чем большеЯ начну со следующего утверждения: Если вы пишете функцию, которая может быть выполнена или как метод класса, или быть внешней по отношению к классу, Вы должны предпочесть ее реализацию без использования метода. Такое решение увеличивает инкапсуляцию класса. Когда Вы думаете об использовании инкапсуляции, Вы должны думать том, чтобы не использовать методы.Удивлены? Читайте дальше.


Рекомендуем почитать
Pro Git

Разработчику часто требуется много сторонних инструментов, чтобы создавать и поддерживать проект. Система Git — один из таких инструментов и используется для контроля промежуточных версий вашего приложения, позволяя вам исправлять ошибки, откатывать к старой версии, разрабатывать проект в команде и сливать его потом. В книге вы узнаете об основах работы с Git: установка, ключевые команды, gitHub и многое другое.В книге рассматриваются следующие темы:основы Git;ветвление в Git;Git на сервере;распределённый Git;GitHub;инструменты Git;настройка Git;Git и другие системы контроля версий.


Java 7

Рассмотрено все необходимое для разработки, компиляции, отладки и запуска приложений Java. Изложены практические приемы использования как традиционных, так и новейших конструкций объектно-ориентированного языка Java, графической библиотеки классов Swing, расширенной библиотеки Java 2D, работа со звуком, печать, способы русификации программ. Приведено полное описание нововведений Java SE 7: двоичная запись чисел, строковые варианты разветвлений, "ромбовидный оператор", NIO2, новые средства многопоточности и др.


MFC и OpenGL

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Симуляция частичной специализации

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка событий в С++

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Питон — модули, пакеты, классы, экземпляры

Python - объектно-ориентированный язык сверхвысокого уровня. Python, в отличии от Java, не требует исключительно объектной ориентированности, но классы в Python так просто изучить и так удобно использовать, что даже новые и неискушенные пользователи быстро переходят на ОО-подход.