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

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

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

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

Он добавил новый механизм, который настоль­ко гибкий, что захват путем перемещения является всего лишь одним из вариантов егоработы. Новая возможность называется инициализирующим захватом (init capture). Онможет делать почти все, что могут делать захваты в С++ 1 1, и еще многое. Единственное,что нельзя выразить с помощью инициализирующего захвата (и от чего, как поясняется6.2. Используйте инициализирующий захват для перемещения объектов в замыкания229в разделе 6.

1 , вам надо держаться подальше), - это режим захвата по умолчанию. (Дляситуаций, охватываемых захватами С++ 1 1 , инициализирующий захват несколько много­словнее, так что там, где справляется захват С++ 1 1 , совершенно разумно использоватьименно его.)Применение инициализирующего захвата делает возможным указать1.имя члена-данныхв классе замыкания, сгенерированном из лямбда-выражения, и2.выражение инициализацииэтого члена-данных.Вот как можно использовать и н ициализирующий захват для перемещенияstd : : un i que_ptr в замыкание:1 1 Некоторый полезный типclass WidgetpuЫ i c :bool i sValidated ( ) const;bool isProcessed ( ) cons t ;bool isArchived ( ) con s t ;priva te :};auto pws td : : make_unique<Widget> ( ) ;=11111111auto fuпc[pwstd: : move (pw) ] 1 1{ return pw- >isValidated ( )11& & pw- >isArchived ( ) ; } ; 1 1==Создание Widge t ;std : : make_uniqueсм .

в разделе 4 . 4Настройка •pwИнициализация членав замыкании с помощьюs t d : : move ( pw)Выделенный текст представляет собой инициализирующий захват. Слева от знакаравенства = находится имя члена-данных в классе замыкания, который вы определяе­те, а справа - инициализирующее выражение. Интересно, что область видимости слеваот "=" отличается от области видимости справа. Область видимости слева - это областьвидимости класса замыкания. Область видимости справа - та же, что и определяемоголямбда-выражения. В приведенном выше примере имя pw слева от = ссылается на чле­ны-данные в классе замыкания, в то время как имя pw справа ссылается на объект, объ­явленный выше лямбда-выражения, т.е.

на переменную, инициализированную вызовомstd : : ma ke_u п i que. Так что "pws t d : : move ( pw ) " означает "создать член-данные pwв замыкании и инициализировать этот член-данные результатом применения std : : moveк локальной переменной pw':Как обычно, код в теле лямбда-выражения находится в области видимости класса за­мыкания, так что использованные в нем pw относятся к члену-данным класса замыкания.Комментарий "настройка * pw" в этом примере указывает, что после созда­ния W i dget с помощью s t d : : ma ke_u n i que и до того, как интеллектуальный указа­тель s t d : : u n i que_pt r на этот W i d g e t будет захвачен лямбда-выражением, W i dget=230Глава 6.

Лямбда-выражениянекоторым образом модифицируется. Если такая настройка не нужна, т.е. если объектWi dget , созданный с помощью s t d : : ma ke_unique, находится в состоянии, приrодномдля захвата лямбда-выражением, локальная переменная pw не нужна, поскольку член­данные класса замыкания может быть непосредственно инициализирован с помощьюstd : : make_unique:auto func = [pw = std.: : make_unique<Widget> ( ) ] / / Инициализация{ return pw- >isValidated ( ) / / члена -данных в замыкании&& pw- >i sArchived ( ) ; } ;/ / результатом вызова make_uniqueИз этоrо должно быть ясно, что понятие захвата в С++ 14 значительно обобщенопо сравнению с С++ 1 1 , поскольку в С++ 1 1 невозможно захватить результат выражения.Поэтому еще одним названием инициализирующеrо захвата является обобщенный за­хват лямбда-выражения (generalized lambda capture).Но что если один или несколько используемых вами компиляторов не поддерживаютинициализирующий захват С++ 14? Как выполнить перемещающий захват в языке, в ко­тором нет поддержки перемещающеrо захвата?Вспомните, что лямбда-выражение - это просто способ rенерации класса и созданияобъекта этоrо типа.

Нет ничеrо, что можно сделать с лямбда-выражением и чеrо нельзябыло бы сделать вручную. Например, код на С++ 1 4, который мы только что рассмотрели,может быть записан на С++ 1 1 следующим образом:class I sValAndArchpuЫic :using DataTypestd : : unique_ptr<Widget > ;explicit IsValAndArch ( DataType & &ptr) / / Применение std : :move/ / описано в разделе 5 . 3: pw ( std : : move (ptr ) ) { }bool operator ( ) ( ) const{ return pw->isValidated ( ) && pw- >isArchived ( ) ; }private :DataType pw ;};auto func=IsVa lAndArch ( s td : : make_unique<Widget> ( ) ) ;Это требует больше работы, чем написание лямбда-выражения, но это не меняет тоrофакта, что если вам нужен класс C++ l l, поддерживающий перемещающую инициализа­цию своих членов-данных, то ваше желание отделено от вас лишь некоторым временемза клавиатурой.Если вы хотите придерживаться лямбда-выражений (с учетом их удобства это, веро­ятно, так и есть), то перемещающий захват можно эмулировать в С++ 1 1 с помощью1.перемещения захватываемого объекта в функциональный объект с помощьюstd : : Ьind2.ипередачи лямбда-выражению ссылки на захватываемый объект.6.2.Используйте инициа л изирующий захват для перемещения объектов в замыкания231Если вы знакомы с s t d : : b iпd, код достаточно прост.

Если нет, вам придется немногопривыкнуть к нему, но игра стоит свеч.Предположим, вы хотите создать локальный std : : vector, разместить в нем соответ­ствующее множество значений, а затем переместить его в замыкание. В С++ 14 это просто:1 1 Объект , перемещаемый1 1 в замыкание11 Наполнение данными[ data = std: : move (data) ] / / Инициализирующий захват{ /* Использование данных */ ) ;std: : vector<douЬle> data;auto fuпcЯ выделил ключевые части этого кода: тип объекта, который вы хотите перемещать( s t d : : vector<douЫe>), имя этого объекта (data) и выражение инициализации для ини­циализирующего захвата ( s t d : : rnove { d a t a ) ).

Далее следует эквивалент этого кодана С++ 1 1 , в котором я выделил те же ключевые части:std : : vector<douЫe> da ta ;// Как и ранее11 Как и ранееauto funcstd : : bind (/ / Эмуляция в С++ 1 1[ ] ( const std : : vector<douЬle>& data) / / инициализирующего11 захвата{ / * Использование данных * / ) ,=std : : move (data));Подобно лямбда-выражениям, std : : Ьiпd создает функциональные объекты. Я назы­ваю функциональные объекты, возвращаемые std : : Ьiпd, Ьiпd-объектами. Первый ар­гумент st d : : Ь i nd - вызываемый объект. Последующие аргументы представляют пере­даваемые этому объекту значения.Вind-объект содержит копии всех аргументов, переданных s t d : : Ьind.

Для каждогоlvаluе-аргумента соответствующий объект в Ьind-объекте создается копированием. Длякаждого rvalue он создается перемещением. В данном примере второй аргумент пред­ставляет собой rvalue (как результат применения std : : rnove; см. раздел 5. 1 ), так что dat aперемещается в Ьiпd-объект. Это перемещающее создание является сутью эмуляции пе­ремещающего захвата, поскольку перемещение rvalue в Ьiпd-объект и есть обходной путьдля перемещения rvalue в замыкание С++ 1 1 .Когда Ьind-объект "вызывается" (т.е. выполняется его оператор вызова функции), со­храненные им аргументы, первоначально переданные в s t d : : Ьi пd, передаются в вызы­ваемый объект.

В данном примере это означает, что когда вызывается Ьind-объект fuпc,лямбда-выражению, переданному в std : : Ьiпd, в качестве аргумента передается создан­ная в fuпc перемещением копия data.Это лямбда-выражение то же самое, что и использованное нами в C++ l4, за исклю­чением добавленного параметра data. Этот параметр представляет собой lvalue-ccылкyна копию data в Ьind-объекте.

(Это не rvalue-ccылкa, поскольку, хотя выражение, ис­пользованное для инициализации копии data (" std : : rnove ( da t a ) "), является rvalue, самапо себе копия dat a представляет собой lvalue.) Таким образом, применение data внутри232Гnава 6. Лямбда-выражениялямбда-выражения будет работать с копией data внутри Ьiпd-объекта, созданной пере­мещением.По умолчанию функция-член operator ( ) в классе замыкания, сгенерированном излямбда-выражения, является const. Это приводит к тому, что все члены-данные в замы­кании в теле лямбда-выражения являются константными. Однако созданная перемеще­нием копия data внутри Ьiпd-объекта не является константной, так что, чтобы предот­вратить модификацию этой копии data внутри лямбда-выражения, параметр лямбда-вы­ражения объявляется как указатель на const.

Если лямбда-выражение было объявленокак mutaЫ е, operator ( ) в его классе замыкания не будет объявлен как const, так чтоцелесообразно опустить const в объявлении параметра лямбда-выражения:auto func1 1 Эмуляция в C++ l lstd : : bind ([ ] (std: : vector<douЬle>& dat a ) mutaЫe 1 1 инициализирующего1 1 захвата для лямбда­{ /* uses of data * / f ,/ / выражения, объяв­std : : move (da t a )// ленного mutaЫe);=Поскольку Ьind-объект хранит копии всех аргументов, переданных s t d : : Ьi nd, Ьind­объект в нашем примере содержит копию замыкания, произведенного из лямбда-выра­жения, являющегося первым аргументом этого объекта.

Следовательно, время жизни за­мыкания совпадает со временем жизни Ьind-объекта. Это важно, поскольку это означает,что, пока существует замыкание, существует и Ьind-объект, содержащий объект, захва­ченный псевдоперемещением.Если вы впервые столкнулись с std : : Ь i nd, вам может понадобиться учебник илисправочник по C++l I, чтобы все детали этого обсуждения встали на свои места в вашейголове.

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

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

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

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