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

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

>class vector {

>public:

> …

> class reference { … };


> reference operator[](size_type n);


>};


>}

В предположении, что вы знаете, что >operator[] у >std::vector обычно возвращает >T&, необычный возвращаемый тип у >operator[] в данном случае должен навести вас на мысль о применении здесь прокси-класса. Уделяя повышенное внимание используемым интерфейсам, часто можно выявить наличие прокси-классов.

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

Идиома явной типизации инициализатора включает объявление переменной с использованием >auto, но с приведением инициализирующего выражения к тому типу, который должен вывести >auto. Например, вот как можно использовать эту идиому, чтобы заставить >highPriority стать переменной типа >bool:

>auto highPriority = static_cast(features(w)[5]);

Здесь >features(w)[5] продолжает, как и ранее, возвращать объект типа >std::vector::reference, но приведение изменяет тип выражения на >bool, который >auto затем выводит в качестве типа переменной >highPriority. Во время выполнения программы объект >std::vector::reference, который возвращается вызовом >std::vector::operator[], преобразуется в значение >bool и в качестве части преобразования выполняется разыменование все еще корректного указателя на >std::vector, возвращенного вызовом >features. Это позволяет избежать неопределенного поведения, с которым мы сталкивались ранее. Затем к битам, на которые указывает указатель, применяется индексация с индексом 5 и полученное значение типа >bool используется для инициализации переменной >highPriority.

В примере с >Matrix идиома явно типизированного инициализатора выглядит следующим образом:

>auto sum = static_cast(m1 + m2 + m3 + m4);

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

>double calcEpsilon(); // Возвращает значение отклонения

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

>float ер = calcEpsilon(); // Неявное преобразование

>                          // double -> float

но это вряд ли выражает мысль “я намеренно уменьшаю точность значения, возвращенного функцией”. Зато это делает идиома явной типизации инициализатора:

>auto ер = static_cast(calcEpsilon());

Аналогичные рассуждения применяются, если у вас есть выражение с плавающей точкой, которое вы преднамеренно сохраняете как целочисленное значение. Предположим, что вам надо вычислить индекс элемента в контейнере с итераторами произвольного доступа (например, >std::vector, >std::deque или >std::array) и вы получаете значение типа >double между >0.0 и >1.0, указывающее, насколько далеко от начала контейнера расположен этот элемент (>0.5 указывает на середину контейнера). Далее, предположим, что вы уверены в том, что полученный индекс можно разместить в >int. Если ваш контейнер — , а значение с плавающей точкой — >d, индекс можно вычислить следующим образом:

>int index = d * (c.size() - 1);

Но здесь скрыт тот факт, что вы преднамеренно преобразуете >double справа от знака “>=” в >int. Идиома явно типизированного инициализатора делает этот факт очевидным:

>auto index = static cast(d * (c.size() - 1));

Следует запомнить

• “Невидимые” прокси-типы могут привести >auto к выводу неверного типа инициализирующего выражения.

• Идиома явно типизированного инициализатора заставляет >auto выводить тот тип, который нужен вам.

Глава 3

Переход к современному С++

Когда дело доходит до умных терминов, С++ 11 и С++14 есть чем похвастаться. >auto, интеллектуальные указатели, семантика перемещения, лямбда-выражения, параллелизм — каждая возможность настолько важна, что я посвящаю ей отдельную главу. Очень важно освоить все эти возможности, но большой путь к эффективному программированию на современном С++ требует множества маленьких шажков. Каждый шаг отвечает на конкретные вопросы, возникающие во время путешествия от С++98 к современному С++. Когда следует использовать фигурные скобки вместо круглых для создания объектов? Почему объявление псевдонимов лучше, чем применение


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

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


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

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


Рекомендуем почитать
Изучаем Java EE 7

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)


Платформа J2Me

Эта книга научит вас, как разрабатывать программное обеспечение для платформы J2ME компании «Sun Microsystems». Эта книга придерживается стиля учебного пособия, это не справочное руководство.Цель — дать вам твердую основу в понятиях и техниках, которая даст вам возможность решиться на самостоятельную разработку качественных приложений.


Виртуальная библиотека Delphi

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


Обработка баз данных на Visual Basic.NET

Это практическое руководство разработчика программного обеспечения на Visual Basic .NET и ADO.NET, предназначенное для создания приложений баз данных на основе WinForms, Web-форм и Web-служб. В книге описываются практические способы решения задач доступа к данным, с которыми сталкиваются разработчики на Visual Basic .NET в своей повседневной деятельности. Книга начинается с основных сведений о создании баз данных, использовании языка структурированных запросов SQL и системы управления базами данных Microsoft SQL Server 2000.


Исчерпывающее руководство по написанию всплывающих подсказок

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


Программное обеспечение встроенных систем. Общие требования к разработке и документированию

Embedded system software. General requirements for development and documentationСтандарт подготовлен в развитие ГОСТ Р ИСО/МЭК 12207-99 «Информационная технология. Процессы жизненного цикла программных средств» с целью учета специфики разработки и документирования программного обеспечения встроенных систем реального времени.