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

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

является ссылка, тип >T выводится как не ссылочный. Вот почему при выводе типа игнорируется “ссылочность” >rx.

Все эти примеры показывают ссылочные параметры, являющиеся lvalue, но вывод типа точно так же работает и для ссылочных параметров rvalue. Конечно, аргументы могут передаваться только ссылочным параметрам, являющимся rvalue, но это ограничение никак не влияет на вывод типов.

Если мы изменим тип параметра >f с >Т& на >const Т&, произойдут небольшие изменения, но ничего удивительного не случится. Константность >cx и >rx продолжает соблюдаться, но поскольку теперь мы считаем, что >param является ссылкой на >const, >const как часть выводимого типа >T не требуется:

>template

>void f(const T& param); // 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*

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

Случай 2. >ParamType является универсальной ссылкой

Все становится менее очевидным в случае шаблонов, принимающих параметры, являющиеся универсальными ссылками. Такие параметры объявляются как ссылки rvalue (т.е. в шаблоне функции, принимающем параметр типа , объявленным типом универсальной ссылки является >Т&&), но ведут себя иначе при передаче аргументов, являющихся lvalue. Полностью вопрос рассматривается в разделе 5.2, здесь приводится его сокращенная версия.

• Если >expr представляет собой lvalue, как , так и >ParamType выводятся как lvalue-ссылки. Это вдвойне необычно. Во-первых, это единственная ситуация в выводе типа шаблона, когда Т выводится как ссылка. Во-вторых, хотя >ParamType объявлен с использованием синтаксиса rvalue-ссылки, его выводимым типом является lvalue-ссылка.

• Если >expr представляет собой rvalue, применяются “обычные” правила (из случая 1). Примеры

>template

>void f(T&& param); // 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. Этого никогда не происходит для неуниверсальных ссылок.

Случай 3. >ParamType не является ни указателем, ни ссылкой

Когда >ParamType не является ни указателем, ни ссылкой, мы имеем дело с передачей по значению:

>template

>void f(T param); // 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. Тот факт, что


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

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


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

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


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

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


Виртуальная библиотека 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 «Информационная технология. Процессы жизненного цикла программных средств» с целью учета специфики разработки и документирования программного обеспечения встроенных систем реального времени.


Как пасти котов. Наставление для программистов, руководящих другими программистами

«Как пасти котов» – это книга о лидерстве и руководстве, о том, как первое совмещать со вторым. Это, если хотите, словарь трудных случаев управления IT-проектами. Программист подобен кошке, которая гуляет сама по себе. Так уж исторически сложилось. Именно поэтому так непросто быть руководителем команды разработчиков. Даже если вы еще месяц назад были блестящим и дисциплинированным программистом и вдруг оказались в роли менеджера, вряд ли вы знаете, с чего надо начать, какой выбрать стиль руководства, как нанимать и увольнять сотрудников, проводить совещания, добиваться своевременного выполнения задач.