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

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

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

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

Этот видповедения может привести программиста к отчаянию - если не к прямому насилию.Можно возразить, что setName не должен был объявлять свой параметр как универ­сальную ссылку. Такие ссылки не могут быть константными (см. раздел 5.2), но setName,безусловно, не должен изменять свой параметр. Вы могли бы указать, что если перегру­зить setName для константных значений lvalue и rvalue, то этой проблемы можно былобы избежать, например, таким образом:class Widget {puЬlic :void setName ( const std: : string& newName ){ name = newNarne ; }void setName (std: : string&& newName)s t d : : rnove ( newName ) ; }{ name=/ / Устанавливается// из const lvalue// Устанавливается11 из rvalue};В данном случае это, безусловно, сработает, но у метода есть и недостатки.

Во-первых,требуется вводить исходный текст большего размера (две функции вместо одного5.3.Испоnьзуйте std::move дл я rvalue-cc ыл oк, а std::forward - дл я универсальных ссыпок1 77шаблона). Во-вторых, это может быть менее эффективным. Например, рассмотрим сле­дующее применение setName:w . setName ( "Adela Nova k" ) ;При наличии версии setName, принимающей универсальную ссылку, функции setNameбудет передан строковый литерал "Adel a Nova k " , в котором он будет передан операторуприсваивания для s t d : : s t r ing внутри w. Таким образом, член-данные name объекта wбудет присвоен непосредственно из строкового литерала; никакого временного объектаs t d : : s t r i ng создаваться не будет.

Однако в случае перегруженных версий setName бу­дет создан временный объект s t d : : s t r i ng, с которым будет связан параметр функцииset Name, и этот временный объект s t d : : s t r i ng будет перемещен в член-данные объ­екта w. Таким образом, вызов setN ame повлечет за собой выполнение одного конструк­тора s t d : : s t r ing (для создания временного объекта), одного перемещающего оператораприсваивания s t d : : st r ing (для перемещения newName в w .

name ) и одного деструктораs t d : : s t ring (для уничтожения временного объекта). Это практически наверняка болеедорогостоящая последовательность операций, чем вызов только одного оператора при­сваивания s t d : : s t r i ng, принимающего указатель cons t c h a r * . Дополнительная стои­мость может варьироваться от реализации к реализации, и стоит ли беспокоиться о ней,зависит от приложения и библиотеки; однако, скорее всего, в ряде случаев замена ша­блона, получающего универсальную ссылку, парой функций, перегруженных для lvalue­и rvalue-ccылoк, приведет к дополнительным затратам времени выполнения.Однако наиболее серьезной проблемой с перегрузкой для lvalue и rvalue является необъем или идиоматичность исходного кода и не производительность времени выполне­ния. Это - плохая масштабируемость проекта.

Widget : : setName принимает только одинпараметр, так что необходимы только две перегрузки. Но для функций, принимающихбольшее количество параметров, каждый из которых может быть как lvalue, так и rvalue,количество перегрузок растет в соответствии с показательной функцией: п параметровтребуют 2" перегрузок. И это еще не самый худший случай. Некоторые функции (на са­мом деле - шаблоны функций) принимают неограниченное количество параметров, каж­дый из которых может быть как lvalue, так и rvalue. Типичными представителями такихфункций являются s t d : : ma ke_s h ared и, начиная с С++ 1 4, st d : : ma ke_uni que (см. раз­дел 4.4). Попробуйте написать объявления их наиболее часто используемых перегрузок:template<class Т, cla s s . .

. Args>/ / Из стандарта C++ l lshared_ptr<T> make shared (Args&& . . . args ) ;template<class Т, class . . . Args>11 Из стандарта С++ 1 4unique_ptr<T> make_unique (Args&& . . . args ) ;Для функций наподобие указанных перегрузка для lvalue и rvalue не является прием­лемым вариантом: единственным выходом является применение универсальных ссылок.А внутри таких функций, уверяю вас, к универсальным ссылкам при их передаче другимфункциям следует применять s t d : : forwa rd. Вот то, что вы должны делать.1 78Глава S. Rvаl uе-ссылки, семантика перемещений и прямая п ередачаНу хорошо, обычно должны. В конечном итоге.

Но не обязательно изначально. В не­которых случаях вы захотите использовать привязку объекта к rvalue-ccылкe или уни­версальной ссылке более одного раза в одной функции, и вы захотите гарантировать,что перемещения не будет, пока вы явно не укажете его выполнить. В этом случае вы за­хотите применить std : : move (для rvalue-ccылoк) или std : : forward (для универсальныхссылок) только к последнему использованию ссылки, например:template<typename Т>void setSignText ( T & & text )11 text - универсальная11 ссылка{/ / Используем text, но не11 изменяем его/ / Получение текущего времениauto now =std : : chrono : : s ystem_clock : : now ( ) ;s ignHistory . add ( now,std: : forward<T> ( text) ) ; / / Условное приведение11 text к rvaluesign .

setText ( text) ;Здесь мы хотим гарантировать, что значение text не изменится вызовом s ign . setText,поскольку мы хотим использовать это значение при вызове s ignHi s tory . add. Следова­тельно, std : : forward применяется только к последнему использованию универсальнойссылки.Для std : : move применяются те же рассуждения (т.е. надо применить s t d : : moveк rvalue-ccылкe только при ее последнем использовании), но важно отметить, что в не­которых редких случаях вы захотите вызвать std : : move_ if _noexcept вместо std : : move.Чтобы узнать, когда и почему, обратитесь к разделу 3.8.Если вы имеете дело с функцией, осуществляющей возврат по значению, и возвраща­ете объект, привязанный к rvalue-ccылкe или универсальной ссылке, вы захотите приме­нять std : : move или s t d : : forward при возврате ссылки.

Чтобы понять, почему, рассмо­трим функцию operator+ для сложения двух матриц, где о левой матрице точно извест­но, что она является rvalue (а следовательно, может повторно использовать свою памятьдля хранения суммы матриц):мatrix//operator+ (мatrix&& lhs , const{lhs += rhs ;return std: : move (lhs) ; / ///Возврат по значениюMatrix& rhs )Перемещение lhs ввозвращаемое значениеС помощью приведения lhs к rvalue в инструкции return (с помощью s t d : : move )lhs будет перемещен в местоположение возвращаемого функцией значения. Если опу­стить вызов std : : move,Matrix/ / Ка к и ранее aboveoperator+ (Matrix&& lhs , const Matrix& rhs ){5.3.Используйте std::move дл я rvalue-ccыnoк, а std::forward - дл я универсальных ссыпок1 79lhs += rhs ;returп lhs;/ / Копирование lhs в1 1 возвращаемое значението тот факт, что l h s представляет собой lvalue, заставит компиляторы вместо пе­ремещени я копировать его в местоположение возвращаемого функцией значения.В предположении, что тип Mat r i x поддерживает перемещающее конструирование,более эффективное, чем копирующее, применение s t d : : move в инструкции returnдает более эффективный код.Если тип Mat rix не поддерживает перемещения, приведение его к rvalue не повре­дит, поскольку rvalue будет просто скопировано копирующим конструктором Mat rix (см.раздел 5.

1 ). Если Matrix позже будет переделан так, что станет поддерживать перемеще­ние, operator+ автоматически использует данное преимущество при следующей компи­ляции. В таком случае ничто не будет потеряно (и возможно, многое будет приобретено)при применении s t d : : move к rvа\uе-ссылкам, возвращаемым из функций, которые осу­ществляют возврат по значению.Для универсальных ссылок и std : : forward ситуация схожа. Рассмотрим шаблонфункции reduceAndCopy, который получает возможно сократимую дробь Fract ion, со­кращает ее, а затем возвращает копию сокращенной дроби. Если исходный объект пред­ставляет собой rvalue, его значение должно быть перенесено в возвращаемое значение(избегая тем самым стоимости создания копии), но если исходный объект - lvalue,должна быть создана фактическая копия:template<typeпame Т>FractionreduceAndCopy ( T & & frac)1 1 Возврат по значению// Универсальнал ссылка{frac .

reduce ( ) ;return std : : forward<T> ( frac ) ; / / Перемещение rvalue и11 копирование lvalue в1 1 возвращаемое значениеЕсли опустить вызов std : : forward, frac будет в обязательном порядке копироватьсяв возвращаемое значение reduceAndCopy.Некоторые программисты берут приведенную выше информацию и пытаются рас­пространить ее на ситуации, в которых она неприменима. Они рассуждают следующимобразом: "если использование std : : move для параметра, являющегося rvаluе-ссылкойи копируемого в возвращаемое значение, превращает копирующий конструктор в пере­мещающий, то я могу выполнить ту же оптимизацию для возвращаемых мною локаль­ных переменных".

Другими словами, они считают, что если дана функция, возвращающаялокальную переменную по значению, такая, как следующая:Widget makeWidget ( ) 1 1 "Коnирующал" версил makeWidget{Widqet w ;1 801 1 Переменнал1 1 Настройка wГлава S. Rvalue-cc ыnки, семантика перемещений и прямая передачаreturn w ;11"Копирование" w в возвращаемое значението они могут "оптимизировать" ее, превратив "копирование" в перемещение:Widget makeWidget ( )11Перемещающая версия makeWidget{Widget w ;return std: : move (w) ; / / Перемещение w в возвращаемое11 значение ( не делайте этого ! )Мое обильное использование кавычек должно подсказать вам, что эти рассуждения нелишены недостатков.

Но почему? Да потому что Комитет по стандартизации уже прошелэтот путь и давно понял, что "копирующая" версия makeWidget может избежать необхо­димости копировать локальную переменную w, если будет создавать ее прямо в памяти,выделенной для возвращаемого значения функции. Это оптимизация, известная как оп­тимизация возвращаемого значения (retшn value optimizationRVO) и с самого началаблагословленная стандартом С++.Формулировка такого благословения - сложное дело, поскольку хочется разрешитьтакое отсутствие копирования только там, где оно не влияет на наблюдаемое поведениепрограммы.

Перефразируя излишне сухой текст стандарта, это благословение на отсут­ствие копирования (или перемещения) локального объекта2 в функции, выполняющейвозврат по значению, дается компиляторам, если ( 1 ) тип локального объекта совпадаетс возвращаемым функцией и (2) локальный объект представляет собой возвращаемоезначение. С учетом этого вернемся к "копирующей" версии makeWidget:-Widget makeWidget ( ) // " Копирующая" версия makeWidget{Widget w ;return w ;/ / "Копирование" w в возвращаемое значениеЗдесь выполняются оба условия, и вы можете доверять мне, когда я говорю вам, чтокаждый приличный компилятор С++ будет использовать RVO для того, чтобы избежатькопирования w.

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

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

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

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