Главная » Просмотр файлов » С. Мейерс - Эффективный и современный C++

С. Мейерс - Эффективный и современный C++ (1114942), страница 59

Файл №1114942 С. Мейерс - Эффективный и современный C++ (С. Мейерс - Эффективный и современный C++) 59 страницаС. Мейерс - Эффективный и современный C++ (1114942) страница 592019-05-08СтудИзба
Просмтор этого файла доступен только зарегистрированным пользователям. Но у нас супер быстрая регистрация: достаточно только электронной почты!

Текст из файла (страница 59)

Но непонятно не только поведение заполнителей.Предположим, у нас есть функция для создания сжатых копий Widgetenum class CompLevel { Low, Norma l , High } ; / / Уровень сжатияWidget compress ( const Widget& w,CompLevel levl ;11 Создание сжатой11 копии wи мы хотим создать функциональный объект, который позволяет нам указывать, на­сколько сильно должен быть сжат конкретный объект Widget w. Представленное нижеприменение std : : Ьind создает такой объект:Widget w;using namespace std : : placeholders ;auto compressRateB=std : : Ыnd ( compre s s , w,1) ;Теперь, когда мы передаем w в std : : Ьi nd, он должен храниться для последующего вы­зова compress. Он сохраняется в объекте cornpressRateB, но как именно - по значениюили по ссылке! Это важно, потому что, если w изменяется между вызовами std : : Ьi ndи cornpres s Ra t eB, хранение w по ссылке будет отражать это изменение, в то время каксохранение по значению - нет.Ответ заключается в том, что оно хранится по значению1, но единственный способузнать это - просто запомнить: в вызове std : : Ь i nd нет никаких признаков этого.

Срав­ните этот подход с лямбда-выражением, в котором захват w по значению или по ссылкевыполняется явно:11 Захват w по значению;auto compressRateL/ / l ev передается по значению[w] (CornpLevel lev){ return cornpres s (w, lev) ; } ;Не менее явно в лямбда-выражения передаются и параметры. Здесь очевидно, что па­раметр lev передается по значению.

Таким образом,compressRateL (CompLevel : : High) ; // arg передается по значению1s t d : : b ind всегда копирует свои аргументы. но вызывающий код может добиться -эфф е ктасохранения аргумента по ссылке путем применения s t d : :auto cornpres sRateB=ref.Результат вызоваs t d : : Ыnd ( compress , s t d : : re f ( w ) , _1 ) ;состоит в том. что cornp r e s sRa t e B действует так, как если бы сохра11ялас1.

ссылкаа не его копия.242Глава 6. Лямбда-выраженияriaобъектw.Но как аргумент передается в объект, получающийся с помощью std : : Ь i nd?compressRateB ( CompLevel : : High ) ; 11 Как передается arg?И вновь единственный способ знать, как работает std : : Ьi nd, - это запомнить. (От­вет заключается в том, что все аргументы, передаваемые Ьind-объектам, передаютсяпо ссылке, поскольку оператор вызова функции для таких объектов использует прямуюпередачу.)По сравнению с лямбда-выражениями код, использующий std : : Ь ind, менее удобо­читаем, менее выразителен и, возможно, менее эффективен. В С++ 14 нет обоснованныхслучаев применения std : : Ь i nd.

Однако в С++ 1 1 применение s t d : : Ь i nd может бытьоправдано в двух ограниченных ситуациях.•Лямбда-выражения С++ 1 1 не предоставляют возможностизахвата перемещением, но его можно эмулировать с помощью комбинации лямбда­выражения и std : : Ьi nd. Детали описываются в разделе 6.2, в котором также пояс­няется, что в С++ 14 поддержка инициализирующего захвата в лямбда-выраженияхустраняет необходимость в такой эмуляции.•Полиморфные функциональные объекты. Поскольку оператор вызова функцииЬind-объекта использует прямую передачу, он может принимать аргументы любоготипа (с учетом ограничений на прямую передачу, описанных в разделе 5.8).

Это мо­жет быть полезным, когда вы хотите связать объект с шаблонным оператором вы­зова функции. Например, для классаЗахват перемещением.class PolyWidget {puЬl i c :template<typename Т>void operator () (const Т& param) const;);s t d : : Ьind может связать Po lyWidget следующим образом:PolyWidget pw;auto boundPW=std : : bind ( pw,1) ;После этого boundPW может быть вызван с разными типами аргументов:boundPW ( l 930 ) ;/ / Передача int в PolyWidget : : operator ( )/ / Передача nullptr в PolyWidget : : operator ( )boundPW (nullptr ) ;boundPW ( "Rosebud" ) ; / / Передача строкового литералаВыполнить это с помощью лямбда-выражений С++ 1 1 невозможно. Однако в С++ 1 4этого легко достичь с помощью лямбда-выражения с параметром auto:6.

4 . Предпочитайте л ямбда-выражения п рименению std::Ьiпd243auto boundPW[pw] ( constauto¶m)11 С++ 1 4{ pw (param) ; } ;Конечно, это крайние случаи, и они встречаются все реже, поскольку поддержкаС++ 1 4 лямбда-выражений компиляторами становится все более распространенной.Когда Ь i nd был неофициально добавлен в С++ в 2005 году, это было существеннымусовершенствованием по сравнению с его предшественником 1 998 года.

Однако добав­ление поддержки лямбда-выражений в C++l l привело к устареванию s t d : : Ы nd, а с мо­мента появления С++ 1 4 для него, по сути, не осталось применений.Сnедует зап омнить•Лямбда-выражения более удобочитаемы, более выразительны и могут быть болееэффеl\Гивными по сравнению с std : : Ы nd.•Только в С++ \ \ s t d : : Ы nd может пригодиться для реализации перемещающегозахвата или для связывания объеl\Гов с шаблонными операторами вызова функции.244Глава 6. Лямбда-выраженияГЛАВА 7Пара лл е ль н ы е вы чис л ен и яОдним из наибольших триумфов С++ 1 1 является включение параллелизма в языкпрограммирования и библиотеку.

Программисты, знакомые с другими потоковыми API(например, pthreads или Windows threads), иногда удивляются сравнительно спартанско­му набору возможностей, предлагаемому С++, но это связано с тем, что по большей частиподдержка параллельности в С++ имеет вид ограничений для разработчиков компилято­ров.

Получаемые в результате языковые гарантии означают, что впервые в истории С++программисты могут писать мноrопоточные приложения со стандартным поведениемна всех платформах. Это создает прочный фундамент, на котором могут быть построенывыразительные библиотеки, а элементы параллелизма в стандартной библиотеке (задачи,фьючерсы, потоки, мьютексы, переменные условий, атомарные объекты и прочие) явля­ются лишь началом того, что обязательно станет более богатым набором инструментовдля разработки параллельного программного обеспечения на С++.В последующих разделах нужно иметь в виду, что стандартная библиотека содержитдва шаблона для фьючерсов: std : : future и std : : shared_ future.

Во многих случаях раз­личия между ними не важны, так что я часто говорю просто о фьючерсах, подразумеваяпри этом обе разновидности.7 1 П редпочитайте про r раммирование на основезадач проrраммированию на основе потоков..Если вы хотите выполнить функцию doAs yncWork асинхронно, у вас есть два основ­ных варианта. Вы можете создать std : : thread и запустить с его помощью doAsyncWork,тем самым прибегнув к подходу на основе потоков:int doAsyncWork ( ) ;std: : thread t ( doAsyncWork) ;Вы также можете передать doAsyncWor k в std : : async, воспользовавшись стратегией, из­вестной как подход на основе задач:auto fut=std: : async (doAsyncWork) ; // " fut"от" future"В таких вызовах функциональный объект, переданный в s t d : : a s ync (например,doAsyncWork ) , рассматривается как задача (task).Подход на основе задач обычно превосходит свой аналог на основе потоков, и небольшиефрагменты кода, с которыми вы встретились выше, показывают некоторые причины этого.Здесь doAsyncwork дает возвращаемое значение, в котором, как мы можем разумно предпо­ложить, заинтересован вызывающий doAsyncwork код.

В случае вызова на основе потоковнет простого способа к нему обратиться. При подходе на основе потоков нет простого спосо­ба получить доступ к вызову. В случае же подхода на основе задач это можно легко сделать,поскольку фьючерс, возвращаемый std : : async, предлагает функцию get. Эта функция getеще более важна, если doAsyncwork генерирует исключение, поскольку get обеспечивает до­ступ и к нему. При подходе на основе потоков в случае генерации функцией doAsyncWorkисключения программа аварийно завершается (с помощью вызова s t d : : terminate ).Более фундаментальным различием между подходами на основе потоков и на основе за­дач является воплощение более высокого уровня абстракции в последнем. Он освобождаетвас от деталей управления потоками, что, кстати, напомнило мне о необходимости расска­зать о трех значениях слова поток (thread) в параллельном программировании на С++.•Аппаратные потоки являются потоками, которые выполняют фактические вычис­ления.

Современные машинные архитектуры предлагают по одному или по несколь­ку аппаратных потоков для каждого ядра процессора.•Программные потоки (известные также как потоки ОС или системные потоки) яв­ляются потоками, управляемыми операционной системой1 во всех процессах и пла­нируемыми для выполнения аппаратными потоками. Обычно можно создать про­граммных потоков больше, чем аппаратных, поскольку, когда программный потокзаблокирован (например, при вводе-выводе или ожидании мьютекса или перемен­ной условия), пропускная способность может быть повышена путем выполнениядругих, незаблокированных потоков.•s t d : : thread представляют собой объекты в процессе С++, которые действуют какдескрипторы для лежащих в их основе программных потоков.

Некоторые объектыstd : : t hread представляют "нулевые" дескрипторы, т.е. не соответствуют программ­ным потокам, поскольку находятся в состоянии, сконструированном по умолчанию(следовательно, без выполняемой функции); потоки, из которых выполнено пере­мещение (после перемещения объект std : : thread, в который оно произошло, дей­ствует как дескриптор для соответствующего программного потока); потоки, у ко­торых выполняемая ими функция завершена; а также потоки, у которых разорванасвязь между ними и обслуживающими их программными потоками.Программные потоки являются ограниченным ресурсом. Если вы попытаетесь соз­дать их больше, чем может предоставить система, будет сгенерировано исключениеstd : : system error. Это так, даже если функция, которую вы хотите запустить, не гене­рирует исключений.

Например, даже если doAsyncwork объявлена как noexcept,_int doAsyncWork ( ) noexoept; / / См . noexcept в разделе 3 . 81 В предположении, что таковая имеется. В некоторых встроенных системах ее нет.246Глава 7. Параллельные вычисленияследующая инструкция может сгенерировать исключение:std : : thread t ( doAsyncWork) ; / / Генерация исключения , если// больше нет доступных потоковХорошо написанное программное обеспечение должно каким-то образом обраба­тывать такую возможность, но как? Один вариант - запустить doAsyncWork в текущемпотоке, но это может привести к несбалансированной нагрузке и, если текущий потокявляется потоком GUI, к повышенному времени реакции системы на действия опера­тора. Другой вариант - ожидание завершения некоторых существующих программныхпотоков с последующей попыткой создания нового объекта std : : thread, но может бытьи так, что существующие потоки ожидают действий, которые должна выполнить функ­ция doAsyncWork (например, ее результата или уведомления переменной условия).Даже если вы не исчерпали потоки, у вас могут быть проблемы с превышением под­писки (oversubscription).

Это происходит, когда имеется больше готовых к запуску (т.е.незаблокированных) программных потоков, чем аппаратных. Когда это случается, плани­ровщик потоков (который обычно представляет собой часть операционной системы) вы­полняет разделение времени для выполнения программных потоков аппаратными. Когдавремя работы одного потока завершается и начинается время работы второго, выполня­ется переключение контекстов. Такие переключения контекстов увеличивают накладныерасходы по управлению потоками и могут оказаться в особенности дорогостоящими,когда аппаратный поток, назначаемый программному, оказывается выполняемым другимядром, не тем, что ранее. В этом случае ( 1 ) кеши процессора обычно оказываются с дан­ными, не имеющими отношения к данному программному потоку, и (2) запуск "нового"программного потока на этом ядре "загрязняет" кеши процессора, заполняя их данными,не имеющими отношения к "старым" потокам, которые выполнялись этим ядром и, ве­роятно, будут выполняться им снова.Избежать превышения подписки сложно, поскольку оптимальное отношение про­граммных и аппаратных потоков зависит от того, как часто запускаются программныепотоки, и может изменяться динамически, например, при переходе программы от рабо­ты по вводу-выводу к вычислениям.

Характеристики

Тип файла
PDF-файл
Размер
12,67 Mb
Тип материала
Высшее учебное заведение

Список файлов книги

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
6417
Авторов
на СтудИзбе
307
Средний доход
с одного платного файла
Обучение Подробнее