Стенли Липпман - Язык программирования C++. Пятое издание

Скачивание начинается... Если скачивание не началось автоматически, пожалуйста нажмите на эту ссылку.
Жалоба
Напишите нам, и мы в срочном порядке примем меры.
Описание книги "Язык программирования C++. Пятое издание"
Описание и краткое содержание "Язык программирования C++. Пятое издание" читать бесплатно онлайн.
Вы держите в руках новое издание популярного и исчерпывающего бестселлера по языку программирования С++, которое было полностью пересмотрено и обновлено под стандарт С++11. Оно поможет вам быстро изучить язык и использовать его весьма эффективными и передовыми способами. В соответствии с самыми передовыми и современными методиками изложения материала авторы демонстрируют использование базового языка и его стандартной библиотеки для разработки эффективного, читабельного и мощного кода.
С самого начала этой книги читатель знакомится со стандартной библиотекой С++, ее самыми популярными функциями и средствами, что позволяет сразу же приступить к написанию полезных программ, еще не овладев всеми нюансами языка. Большинство примеров из книги было пересмотрено так, чтобы использовать новые средства языка и продемонстрировать их наилучшие способы применения. Эта книга — не только проверенное руководство для новичков в С++, она содержит также авторитетное обсуждение базовых концепций и методик языка С++ и является ценным ресурсом для опытных программистов, особенно желающих побыстрей узнать об усовершенствованиях С++11.
Стенли Б. Липпман работал старшим консультантом в Jet Propulsion Laboratory, архитектором группы Visual С++ корпорации Microsoft, техническим сотрудником Bell Laboratories и главным инженером- программистом по анимации в кинокомпаниях Disney, DreamWorks, Pixar и PDI.
Жози Лажойе, работающий ныне в кинокомпании Pixar, был членом канадской группы разработчиков компилятора C/C++ корпорации IBM, а также возглавлял рабочую группу базового языка С++ в составе международной организации по стандартизации ANSI/ISO.
Барбара Э. Му имеет почти тридцатилетний опыт программирования. На протяжении пятнадцати лет она работала в компании AT&T, сотрудничая с Бьярне Страуструпом, автором языка С++, и несколько лет руководила группой разработчиков С++.
• Узнайте, как использовать новые средства языка С++11 и стандартной библиотеки для быстрого создания надежных программ, а также ознакомьтесь с высокоуровневым программированием
• Учитесь на примерах, в которых показаны передовые стили программирования и методики проектирования
• Изучите принципы и узнайте почему язык С++11 работает именно так
• Воспользуйтесь множеством перекрестных ссылок, способных помочь вам объединить взаимосвязанные концепции и проникнуть в суть
• Ознакомьтесь с современными методиками обучения и извлеките пользу из упражнений, в которых подчеркиваются ключевые моменты, позволяющие избежать проблем
• Освойте лучшие методики программирования и закрепите на практике изученный материал
Исходный код примеров можно загрузить с веб-страницы книги на сайте издательства по адресу: http://www.williamspublishing.com
Теперь рассмотрим второе присвоение, которое вызывает функцию std::move(s1). В этом вызове аргументом функции move() является l-значение. Поэтому на сей раз:
• выведенным типом Т будет string& (ссылка на тип string, а не просто string);
• следовательно, экземпляр шаблона remove_reference создается с типом string&;
• тип-член type класса remove_reference<string&> будет иметь тип string;
• типом возвращаемого значения функции move() все еще будет string&&;
• параметр t функции move() будет создан как экземпляр string& &&, который сворачивается в string&.
Таким образом, этот вызов создает экземпляр шаблона move<string&>, который является точно тем, что необходимо для связи ссылки на r-значение с l-значением.
string&& move(string &t)
Тело этого экземпляра возвращает тип static_cast<string&&>(t). В данном случае типом t является string&, который приведение преобразует в тип string&&.
Оператор static_cast поддерживает приведение l-значения к ссылке на r-значениеОбычно оператор static_cast может выполнить только доступные преобразования (см. раздел 16.3). Однако для ссылок на r-значение есть специальное разрешение: даже при том, что нельзя неявно преобразовать l-значение в ссылку на r-значение, используя оператор static_cast, можно явно привести l-значение к ссылке на r-значение.
Привязка ссылки на r-значение к l-значению создает код, который работает с разрешением ссылке на r-значение заменять l-значение. Иногда, как в случае с функцией reallocate() класса StrVec (см. раздел 13.6.1), известно, что замена l-значения безопасна. Разрешая осуществлять это приведение, язык позволяет его использование. Вынуждая использовать приведение, язык пытается предотвратить его случайное использование.
И наконец, хотя такие приведения можно написать непосредственно, намного проще использовать библиотечную функцию move(). Кроме того, использование функции std::move() существенно облегчает поиск в коде места, потенциально способного заменить l-значения.
Упражнения раздела 16.2.6Упражнение 16.46. Объясните, что делает этот цикл из функции StrVec::reallocate() (раздел 13.5):
for (size_t i = 0; i != size(); ++i)
alloc.construct(dest++, std::move(*elem++));
16.2.7. Перенаправление
Некоторые функции должны перенаправлять другим функциям один или несколько своих аргументов с неизменными типами. В таких случаях необходимо сохранить всю информацию о перенаправленных аргументах, включая то, является ли тип аргумента константой и является ли аргумент l- или r-значением.
В качестве примера напишем функцию, получающую вызываемое выражение и два дополнительных аргумента. Функция вызовет предоставленное вызываемое выражение с другими двумя аргументами в обратном порядке. Вот первый фрагмент функции обращения:
// шаблон, получающий вызываемое выражение и два параметра
// вызывает предоставленное выражение с "обращенными" параметрами
// flip1 - неполная реализация: спецификатор const верхнего уровня и
// ссылки теряются
template <typename F, typename T1, typename T2>
void flip1(F f, T1 t1, T2 t2) {
f(t2, t1);
}
Этот шаблон работает прекрасно, пока он не используется для вызова функции со ссылочным параметром:
void f(int v1, int &v2) // обратите внимание, v2 - ссылка
{
cout << v1 << " " << ++v2 << endl;
}
Здесь функция f() изменяет значение аргумента, привязанного к параметру v2. Но если происходит вызов функции f() через шаблон flip1, внесенные функцией f() изменения не затронут первоначальный аргумент:
f(42, i); // f() изменяет свой аргумент i
flip1(f, j, 42); // вызов f() через flip1 оставляет j неизменным
Проблема в том, что j передается параметру t1 шаблона flip1. Этот параметр имеет простой, не ссылочный тип int, а не int&. Таким образом, этот вызов создает следующий экземпляр шаблона flip1:
void flip1(void(*fcn)(int, int&), int t1, int t2);
Значение j копируется в t1. Ссылочный параметр в функции f() связан с t1, а не с j.
Определение параметров функции, хранящих информацию типаЧтобы передать ссылку через функцию, необходимо переписать ее так, чтобы параметры сохраняли принадлежность своих аргументов к l-значениям. Немного поразмыслив, можно предположить, что константность аргументов также необходимо сохранить.
Всю информацию о типе аргумента можно сохранить, определив соответствующий ему параметр функции как ссылку на r-значение параметра типа шаблона. Использование ссылочного параметра (l- или r-значение) позволяет сохранить константность, поскольку спецификатор const в ссылочном типе нижнего уровня. Благодаря сворачиванию ссылок (см. раздел 16.2.5), если определить параметры функции как T1&& и T2&&, можно сохранить принадлежность к l- или r-значениям аргументов функции (см. раздел 16.2.5):
template <typename F, typename T1, typename T2>
void flip2(F f, T1 &&t1, T2 &&t2) {
f(t2, t1);
}
Как и прежде, если происходит вызов flip2(f, j, 42), l-значение j передается параметру t1. Однако в функции flip() для T1 выводится тип int&, а значит, тип t1 сворачивается в int&. Ссылка t1 связана с j. Когда функция flip() вызывает функцию f(), ссылочный параметр v2 в функции f() привязан к t1, который, в свою очередь, привязан к j. Когда функция f() осуществляет инкремент v2, это изменяет значение j.
Параметр функции, являющийся ссылкой на r-значение параметра типа шаблона (т.е. Т&&), сохраняет константность и принадлежность к l- или r-значениям соответствующих ему аргументов.
Эта версия функции flip() решает одну половину проблемы. Она работает прекрасно с функциями, получающими ссылки на l-значение, но неприменима для вызова функций с параметрами ссылок на r-значение. Например:
void g(int &&i, int& j) {
cout << i << " " << j << endl;
}
Если попытаться вызывать функцию g() через функцию flip(), то для параметра ссылки на r-значение функции g() будет передан параметр t2. Даже если функции flip() было передано r-значение, функции g() будет передан параметр, носящий в функции flip() имя t2:
flip2(g, i, 42); // ошибка: нельзя инициализировать int&& из l-значения
Параметр функции, как и любая другая переменная, является выражением l-значения (см. раздел 13.6.1). В результате вызов функции g() в функции flip() передает l-значение параметру ссылки на r-значение функции g().
Использование функции std::forward() для сохранения информации типа в вызовеЧтобы передать функции flip() параметры способом, сохраняющим типы первоначальных аргументов, можно использовать новую библиотечную функцию forward(). Как и функция move(), функция forward() определяется в заголовке utility. В отличие от функции move(), функцию forward() следует вызывать с явным аргументом шаблона (см. раздел 16.2.2). Для этого явного аргумента типа функция forward() возвращает ссылку на r-значение. Таким образом, типом возвращаемого значения функции forward<T> будет Т&&.
Обычно функцию forward() используют для передачи параметра функции, который определен как ссылка на r-значение, параметру типа шаблона. Благодаря сворачиванию ссылок для типа возвращаемого значения функция forward() сохраняет характер (l- или r-значение) переданного ей аргумента:
template <typename Type> intermediary(Type &&arg) {
finalFcn(std::forward<Type>(arg)); // ...
}
Здесь Type используется как тип явного аргумента шаблона функции forward() (выводимый из arg). Поскольку arg — это ссылка на r-значение для параметра типа шаблона, параметр Type представит всю информацию типа в аргументе, переданном параметру arg. Если этот аргумент будет r-значением, то параметр Type будет иметь обычный (не ссылочный) тип и функция forward<Type>() возвратит Type&&. Если аргумент будет l-значением, то (благодаря сворачиванию ссылок) типом параметра Type будет ссылка на l-значение. В данном случае типом возвращаемого значения будет ссылка на r-значение для типа ссылки на l-значение. Снова благодаря сворачиванию ссылок (на сей раз для типа возвращаемого значения) функция forward<Type>() возвратит тип ссылки на l-значение.
Подписывайтесь на наши страницы в социальных сетях.
Будьте в курсе последних книжных новинок, комментируйте, обсуждайте. Мы ждём Вас!
Похожие книги на "Язык программирования C++. Пятое издание"
Книги похожие на "Язык программирования C++. Пятое издание" читать онлайн или скачать бесплатно полные версии.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
Отзывы о "Стенли Липпман - Язык программирования C++. Пятое издание"
Отзывы читателей о книге "Язык программирования C++. Пятое издание", комментарии и мнения людей о произведении.