Стенли Липпман - Язык программирования C++. Пятое издание
- Название:Язык программирования C++. Пятое издание
- Автор:
- Жанр:
- Издательство:Издательский дом Вильямс
- Год:2014
- Город:Москва
- ISBN:978-5-8459-1839-0
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стенли Липпман - Язык программирования C++. Пятое издание краткое содержание
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под
. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман Жози Лажойе Барбара Э. Му • Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Язык программирования C++. Пятое издание - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
16.2.5. Дедукция аргумента шаблона и ссылки
Чтобы лучше понять дедукцию типа, рассмотрим такой вызов функции где параметр функции p
является ссылкой на параметр типа шаблона T
:
template void f(Т &p);
Обратите внимание на два момента: здесь применяются обычные правила привязки ссылок; и спецификаторы const
здесь нижнего уровня, а не верхнего.
Когда параметр функции представляет собой обычную ссылку (l-значение) на параметр типа шаблона (т.е. имеющего форму T&
), правила привязки гласят, что передавать можно только l-значения (например, переменная или выражение, возвращающее ссылочный тип). Этот аргумент может быть или не быть константным. Если аргумент будет константой, то тип Т
будет выведен как константный:
template void f1(Т&); // аргумент должен быть l-значением
// вызовы f1() используют ссылочный тип аргумента как тип параметра
// шаблона
f1(i); // i - это int; параметр шаблона Т - это int
f1(ci); // ci - это const int; параметр шаблона Т - это const int
f1(5); // ошибка: аргумент ссылочного параметра
// должен быть l-значением
Если параметр функции имеет тип const Т&
, обычные правила привязки гласят, что можно передать любой вид аргумента — объект (константный или нет), временный объект или литеральное значение. Когда сам параметр функции является константой, выведенный для параметра Т
тип не будет константным типом. Константность является частью типа параметра функции, и поэтому она не становится также частью типа параметра шаблона:
template void f2(const T&); // может получать r-значения
// параметр в f2() - это const & const в аргументе неуместен
// в каждом из этих трех вызовов параметр функции f2() выводится
// как const int&
f2(i); // i - это int; параметр шаблона Т - это int
f2(ci); // ci - это const int, но параметр шаблона T - это int
f2(5); // параметр const & может быть привязан к r-значению;
// Т - это int
Когда параметр функции является ссылкой на r-значение (см. раздел 13.6.1), т.е. имеет форму Т&&
, обычные правила привязки гласят, что этому параметру можно передать r-значение. При этом дедукция типа ведет себя таким же образом, как дедукция обычного ссылочного параметра функции на l-значение. Выведенный тип для параметра Т
— это тип r-значения:
template void f3(T&&);
f3(42); // аргумент - это r-значение типа int; параметр
// шаблона Т - это int
Предположим, что i
является объектом типа int
. Можно подумать, что такой вызов, как f3(i)
, будет недопустим. В конце концов, i
— это l-значение, а ссылку на r-значение обычно нельзя связать с l-значением. Однако язык определяет два исключения из обычных правил привязки, которые позволяют это. На этих исключениях из правил основан принцип работы таких библиотечных функций, как move()
.
Первое исключение относится к дедукции типа для ссылочного параметра на r-значение. Когда l-значение (например, i
) передается параметру функции, являющемуся ссылкой на r-значение на параметр типа шаблона (например, Т&&
), компилятор выводит параметр типа шаблона как тип ссылки на l-значение аргумента. Поэтому, когда происходит вызов f3(i)
, компилятор выводит тип Т
как int&
, а не int
.
Выведение типа Т
как int&
, казалось бы, означает, что параметр функции f3()
будет ссылкой на r-значение типа int&
. Обычно нельзя (непосредственно) определить ссылку на ссылку (см. раздел 2.3.1). Но это можно сделать косвенно, через псевдоним типа (см. раздел 2.5.1) или через параметр типа шаблона.
В таких ситуациях проявляется второе исключение из обычных правил привязки: если косвенно создать ссылку на ссылку, то эти ссылки " сворачиваются " (collapse). Во всех случаях кроме одного сворачивание ссылок формирует обычный тип ссылки на l-значение. Новый стандарт дополняет правила свертывания, включая ссылки на r-значение. Ссылки сворачиваются, формируя ссылку на r-значение только в специфическом случае ссылки на r-значение на ссылку на r-значение. Таким образом, для данного типа X:
• X& &
, X& &&
и X&& &
сворачиваются в тип X&
.
• Тип X&& &&
сворачивается в тип X&&
.
Сворачивание ссылок применимо только тогда, когда ссылка на ссылку создается косвенно, как в псевдониме типа или параметре шаблона.
Комбинация правил свертывания ссылок и специального правила дедукции типа для ссылочных на r-значения параметров означает, что можно вызвать функцию f3()
для l-значения. Когда параметру функции f3()
(ссылке на r-значение) передается l-значение, компилятор выведет тип T
как тип ссылки на l-значение:
f3(i); // аргумент - это l-значение; параметр Т шаблона - это int&
f3(ci); // аргумент - это l-значение;
// параметр Т шаблона - это const int&
Когда параметр T
шаблона выводится как ссылочный тип, правило свертывания гласит, что параметр функции T&&
сворачивается в тип ссылки на l-значение. Например, результирующий экземпляр для вызова f3(i)
получится примерно таким:
// недопустимый код, приведен только для примера
void f3(int& &&); // когда T - это int&, параметр
// функции - это int& &&
Параметр функции f3()
— это Т&&
, а T
— это int&
, таким образом, Т&&
будет int& &&
, что сворачивается в int&
. Таким образом, даже при том, что формой параметра функции f3()
будет ссылка на r-значение (т.е. T&&
), этот вызов создаст экземпляр функции f3()
с типом ссылки на l-значение (т.е. int&
):
void f3(int&); // когда T - это int&, параметр функции
// сворачивается в int&
У этих правил есть два важных следствия.
• Параметр функции, являющийся ссылкой на r-значение для параметра типа шаблона (например, Т&&
), может быть связан с l-значением.
• Если аргумент будет l-значением, то выведенный тип аргумента шаблона будет типом ссылки на l-значение, и экземпляр параметра функции будет создан как (обычный) параметр ссылки на l-значение ( Т&
).
Стоит также обратить внимание на то, что параметру функции Т&&
косвенно можно передать аргумент любого типа. Параметр такого типа может использоваться с r-значениями, а, как было продемонстрировано только что, также и с l-значениями.
Интервал:
Закладка: