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

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

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

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

Вот основные моменты, которые должны быть понятными.•Невозможно выполнить перемещение объекта в замыкание С++ 1 1, но можно вы­полнить перемещение объекта в Ьind-объект С++ 1 1 .•Эмуляция захвата перемещением в С++ 1 1 состоит в перемещении объекта в Ьind­объект с последующей передачей перемещенного объекта в лямбда-выражениепо ссылке.•Поскольку время жизни Ьind-объекта совпадает с таковым для замыкания, можнорассматривать объекты в Ьind-объекте так, как будто они находятся в замыкании.В качестве второго примера применения std : : Ь i nd для эмуляции перемещающегозахвата рассмотрим пример кода С++ 1 4, который мы видели ранее и который создаетstd : : unique_ptr в замыкании:auto func[pwstd: : make_unique<Widget> ( ) ] / / Как и ранее,/ / создает pw{ return pw - >i sVa lidated ( )& & pw->isArchived ( ) ; ) ;1 1 в замыкании==А вот как выглядит его эмуляция на С++ 1 1:6.2.Испоnьзуйте инициаnизирующий захват для перемещения объектов в замыкания233auto func=std : : bind ([ ] ( const std: : unique_ptr<Wiclget>& pw){ re turn pw - >isValidated ( )& & pw->isArchived ( ) ; } ,std: : make_unique<Wiclget> ( ));Забавно, что я показываю, как использовать s t d : : Ьind для обхода ограничений лямб­да-выражений в С++ 1 1 , поскольку в разделе 6.4 я выступаю как сторонник применениялямбда-выражений вместо s t d : : Ьind.

Однако в данном разделе поясняется, что в С++ 1 1имеются ситуации, когда может пригодиться s t d : : Ь i nd, и это одна из них. (В С++14 та­кие возможности, как инициализирующий захват и параметры auto, устраняют такиеситуации.)Сnедует запомнить•Для перемещения объектов в замыкания используется инициализирующий захватС++14.•В С++ 1 1 инициализирующий захват эмулируется с помощью написания классоввручную или применения s t d : : Ьi nd.6.3 . Испопьзуйте параметры decl type дпя auto & &дпя передачи с помощью s td : : forwardОдной из самых интересных возможностей С++ 14 являются обобщенные лямбда-вы­ражения - лямбда-выражения, в спецификации параметров которых используется клю­чевое слово auto.

Реализация этой возможности проста: operator ( ) в классе замыканиялямбда-выражения является шаблоном. Например, для лямбда-выраженияauto f = [ ] ( auto х) { return normal i ze ( х ) ; } ;оператор вызова функции класса замыкания имеет следующий вид:class SomeCompi lerGeneratedClassName {puЬlic :template<typename Т>/ / См . возвращаемый тип autoauto operator ( ) ( Т х) const / / в разделе 1 . 3{ return normal i ze ( x ) ; }1 1 Прочая функциональность11 класса замыкания};В этом примере единственное, что делает лямбда-выражение с параметром х, - это пере­дает его функции norma l i ze. Если пorma l i ze рассматривает значения lvalue не так, какзначения rvalue, это лямбда-выражение написано некорректно, поскольку оно всегдапередает функции norma l i ze lvalнe (параметр х ) , даже если переданный в лямбда-выра­жение аргумент представляет собой rvalue.234Глава б.

Лямбда-выраженияКорректным способом написания лямбда-выражения является прямая передача хв norma l i ze . Это требует внесения в код двух изменений. Во-первых, х должен быть уни­версальной ссылкой (см. раздел 5.2), а во-вторых, он должен передаваться в norma l i z eс использованием std : : forward (см.

раздел 5.3). Концептуально это требует тривиаль­ных изменений:auto f[ ] (auto&& х ){ return norma l i ze (std: : forward<???> (x) ) ; 1 :=Однако между концепцией и реализацией стоит вопрос о том, какой тип передаватьв std : : forward, т.е. вопрос определения того, что должно находиться там, где я написал" ? ? ?':Обычно, применяя прямую передачу, вы находитесь в шаблонной функции, прини­мающей параметр типа т, так что вам надо просто написать s t d : : forward<T>.

В обоб­щенном лямбда-выражении такой параметр типа т вам недоступен. Имеется т в шабло­низированном операторе operator ( ) в классе замыкания, сгенерированном лямбда-вы­ражением, но сослаться на него из лямбда-выражения невозможно, так что это никак непомогает.В разделе 5.6. поясняется, что если lvalue-apryмeнт передается параметру, являюще­муся универсальной ссылкой, то типом этого параметра становится lvalue-ccылкa. Еслиже передается rvalue, параметр становится rvаluе-ссылкой. Это означает, что вне лямбда­выражения мы можем определить, является ли переданный аргумент lvalue или rvalue,рассматривая тип параметра х.

Ключевое слово decl t ype дает нам возможность сде­лать это (см. раздел 1 .3). Если было передано lvalue, dec l t ype ( х ) даст тип, являющийсяlvаluе-ссылкой. Если же было передано rvalue, decl t уре ( х ) даст тип, являющийся rvаluе­ссылкой.В разделе 5.6 поясняется также, что при вызове std : : fo rward соглашения требуют,чтобы для указания lvalue аргументом типа была lvalue-ccылкa, а для указания rvalue тип, не являющийся ссылкой. В нашем лямбда-выражении, если х привязан к lvalue,declt уре ( х ) даст lvalue-ccылкy. Это отвечает соглашению.

Однако, если х привязанк rvalue, d e c l t уре ( х ) вместо типа, не являющегося ссылкой, даст rvalue-ccылкy. Новзглянем на пример реализации std : : forward в С++ 14 из раздела 5.6:/ / В пространствеtemplate<typename Т>Т&& forward ( remove_reference_t<T>& param) // имен stdreturn static_cast<T&&> ( param) ;Если клиентский код хочет выполнить прямую передачу rvalue типа Widget, он обыч­но инстанцирует st d : : forward типом W idget (т.е. типом, не являющимся ссылочным),и шаблон std : : forward дает следующую функцию:Widget& & forward (Widget& param){б.3.11 Инстанцирование для1 1 std: : forward, когдаИспопьзуйте п араметры decltype дл я auto&& для передачи с помощью std::forward235return static_ca st<Widqet& & > (param) ; // Т является WidgetНо рассмотрим, что произойдет, если код клиента намерен выполнить прямую пере­дачу того же самого rvalue типа Widget, но вместо следования соглашению об определе­нии Т как не ссылочного типа определит его как rvа\uе-ссылку, т.е.

рассмотрим, что слу­чится, если Т определен как W idge t & & . После начального инстанцирования std : : forwa rdи применения std : : remove_re fe rence_ t, но до свертывания ссылок (еще раз обратитеськ разделу 5.6) std : : forward будет выглядеть следующим образом:Widqet&& & & forward (Widqet& param){return static_cast<Widqet&& &&> ( param) ;/ / (до11 Инстанцирование11 std : : forward nри// Т, равном Widget & &сворачивания ссьuюк)Применение правила сворачивания ссылок о том, что rvа\uе-ссылка на rvа\uе-ссылку ста­новится одинарной rvа\uе-ссылкой, приводит к следующему инстанцированию:Widge t & & forward (Widget& param){return static_cast<Widge t & & > (param) ;1 1 ( после11 Инстанцирование11 std : : forward при/ / Т , равном Widget&&сворачивания ссьmок )Если вы сравните это инстанцирование с инстанцированием, получающимся в резуль­тате вызова s t d : : forward с т, равным Widget, то вы увидите, что они идентичны.

Это оз­начает, что инстанцирование s t d : : forward типом, представляющим собой rvа\uе-ссылку,дает тот же результат, что и инстанцирование типом, не являющимся ссылочным.Это чудесная новость, так как dec l t ype ( х ) дает rvа\uе-ссылку, когда в качестве ар­гумента для параметра х нашего лямбда-выражения передается rvalue. Выше мы уста­новили, что, когда в наше лямбда-выражение передается lvalue, dec lt уре ( х ) дает со­ответствующи й соглашению тип для передачи в s t d : : forwa rd, и теперь мы понимаем,что для rvalue dec l t ype ( х ) дает тип для передачи st d : : fo rwa rd, который не соответ­ствует соглашению, но тем не менее приводит к тому же результату, что и тип, соот­ветствующий соглашению. Так что как для lvalue, так и для rvalue передача declt ype ( х )в s t d : : forward дает н ам желаемый результат.

Следовательно, наше лямбда-выражениес прямой передачей может быть записано следующим образом:auto f[ ] (auto&& х ){ return norma l i ze (std : : forward<decltype (x) > ( x ) ) ; ) ;=Чтобы это лямбда-выражение принимало любое количество параметров, нам, по сути,надо только шесть точек, поскольку лямбда-выражения в С++ 14 могут быть с перемен­ным ч ислом аргументов:auto f[ ] ( auto&& .

. . x s ){ return normal i ze ( std : : forward<decltype ( xs ) > ( xs ) . . . ) ; ) ;=236Глава б. Лямбда-выраженияСл едует запомнить•Используйте для параметров а u t о & & при их прямой передаче с помощьюs t d : : forward ключевое слово decl t ype.6.4. Предпочитайте nямбда-выраженияприменению s td : : Ьindstd : : Ьi пd в C++ l l является преемником s td : : Ьiпdlst и s t d : : Ьiпd2пd из С++98,но неформально этот шаблон является частью стандартной библиотеки еще с 2005 года.Именно тогда Комитет по стандартизации принял документ, известный как TRl, которыйвключал спецификацию Ь i пd. (В TRl Ь i пd находился в отдельном пространстве имен,так что обращаться к нему надо было как к s t d : : t r 1 : : Ьi пd, а не к s t d : : Ьi пd, а крометого, некоторые детали его интерфейса были иными.) Эта история означает, что неко­торые программисты имеют за плечами десятилетний опыт использования s t d : : Ь i пd.Если вы один из них, вы можете не быть склонными отказываться от столь долго веройи правдой служившего вам инструмента.

Это можно понять, и все же в данном случаелучше его сменить, поскольку лямбда-выражения С++ 1 1 почти всегда являются лучшимвыбором, чем std : : Ь iпd. Что касается С++ 14, то здесь лямбда-выражения являются на­стоящим кладом.В этом разделе предполагается, что вы хорошо знакомы с std : : Ьiпd. Если это не так,вы, вероятно, захотите получить базовые знания о нем, прежде чем продолжить чтение.Что ж, это похвально, тем более что никогда не знаешь, не встретишься ли с применени­ем std : : Ьiпd в коде, который придется читать или поддерживать.Как и в разделе 6.2, я называю функциональные объекты, возвращаемые std : : Ьi пd,Ьiпd-объектами.Наиболее важная причина, по которой следует предпочитать лямбда-выражения, за­ключается в их большей удобочитаемости.

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

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

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

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