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

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

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

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

push_back ( s td : : forward<T> ( newName ) ) ;11 Применение std : : forward описано в разделе 5 . 31;Это приводит к уменьшению количества исходного текста, с которым приходится ра­ботать, но применение универсальных ссылок влечет за собой другие сложности. Будучишаблоном, реализация addName обычно должна располагаться в заголовочном файле. Вобъектном коде такой подход может дать несколько функций, так как инстанцирова­ние будет выполняться по-разному не только для lvalue и rvalue, но и для s t d : : stringи типов, преобразуемых в std : : s t r i ng (см.

раздел 5.3). В то же время имеются типыаргументов, которые не могут быть переданы с помощью универсальной ссылки (см. раз­дел 5.8), и если клиент передаст аргументы некорректного типа, сообщения компилятораоб ошибках могут быть приводящими в трепет (см. раздел 5.5).Было бы неплохо, если бы имелся способ написания функций наподобие addName,таких, чтобы lvalue копировались, rvalue перемещались, при этом (в исходном текстеи объектном коде) имелась бы только одна функция и при этом можно было избежатьнеприятностей, связанных с универсальными ссылками. И такой способ есть. Все, чтоот вас требуется, - забыть об одном из первых правил, с которыми вы познакомилиськак программист на С++.

Это правило, гласящее, что следует избегать передачи пользо­вательских типов по значению. Для параметров наподобие newName в функциях наподо­бие addName передача по значению может быть вполне разумной стратегией.Перед тем как начать выяснение, почему передача по значению может быть хорошимрешением для newName и addName, посмотрим, как она может быть реализована:282Гл ава 8.

Тонкостиclass Widget [puЫic :void addName ( std: : string newName ){ names . push_back ( s td : :move (newName) ) ;)11 lvalue или11 rva lue ;11 перемещаем его;Единственной неочевидной частью этого кода является применение std : : move к параме­тру newName. Обычно s t d : : move используется с rvаluе-ссылками, но в данном случае мызнаем, что ( 1 ) newName представляет собой объект, полностью независимый от того, чтопередает вызывающая функция, так что изменение newName не влияет на вызывающуюфункцию, и (2) это последнее применение newName, так что его перемещение н икак невлияет на остальную часть функции.Тот факт, что существует только одна функция addName, поясняет, как мы избегаемдублирования кода - как исходного, так и объектного.

Мы не используем универсаль­ную ссылку, так что данный подход не ведет к увеличению заголовочных файлов, стран­ным неприятностям или непонятным сообщениям об ошибках. Но что можно сказатьоб эффективности такого дизайна? Мы же выполняем передачу по значению. Не слиш­ком ли она дорога?В С++98 можно держать пари, что так и есть. Независимо от того, что передает вызы­вающая функция, параметр newName создается с помощью копирующего конструктора.Однако в С++ 1 1 newName будет создаваться с помощью копирующего конструированиятолько для lvalue.

В случае rvalue этот объект создается с помощью перемещающего кон­структора. Вот, взгляните:Widget w;std : : string name ( " Bart" ) ;w . addName (name ) ;11 Вызов addNameсlvaluew . addName (name + "Jenne " ) ; / / Вызов addName11 ( см . ниже)сrvalueВ первом вызове addName (при передаче name ) параметр newName инициализируется зна­чением lvalue. Поэтому объект newName создается путем копирования, так же, как этобыло бы в С++98. Во втором вызове newName инициализируется объектом std : : string,полученным в результате вызова оператора operator+ для std : : string (т.е.

выполненияоперации добавления). Этот объект представляет собой rvalue, и newName, таким обра­зом, создается перемещением.Итак, lvalue копируются, а rvalue перемещаются, как мы и хотели. Здорово, правда?Здорово, но есть несколько моментов, которые следует иметь в виду. Для облегченияпонимания вспомним три рассмотренные версии функции addName:class Widget { // Подход 1 : перегрузка для lvaluepuЫic :void addName (const std: : string& newName )иrvalue8 .

1 . Рассмотрите передачу по значению дл я копируемых параметров""283{ names . push_back (newName ) ; }void addName (std: : string&& newName ){ names . push_back ( s td : : move (newName ) ) ;private :std: : vector<std : : string> names ;};class Widget { / / Подход 2 : применение универсальной ссьmкиpuЬlic :teмplate<t:ypename Т>void addName (T&& newName )names . push_bac k ( s td : : forward<T> (newName ) ) ;};class Widget { / / Подход 3 : передача по значениюpuЬli c :void addName (std: : string newName ){ names . push_bac k ( s td : : move (newName ) ) ;};Я буду говорить о первых двух версиях как о "подходе с передачей ссылки", посколькуони обе передают параметры по ссылке.Вот два сценария вызова, которые мы рассмотрели:Widget w;std: : string name ( " Bart " ) ;w .

addName ( name ) ;1 1 Передача lvaluew . addName (name + " Jenne " ) ; / / Передача rvalueДавайте теперь рассмотрим стоимость (в операциях копирования и перемещения) до­бавления имени в Widget для приведенных сценариев и каждой из трех рассмотренныхреализаций a ddName. Мы будем игнорировать оптимизирующие возможности компиля­торов по удалению копирований и перемещений, поскольку такая оптимизация зависитот контекста и компилятора и с практической точки зрения на суть анализа не влияет.•Переrрузка.

Независимо от передачи lvalue или rvalue аргумент вызывающейфункции связан со ссылкой по имени newName. Это ничего не стоит в смысле опе­раций копирования и перемещения. В перегрузке для lvalue newName копируетсяв W i dg e t : : n ame s . В перегрузке для rvalue объект перемещается.

Итоговая стои­мость: одно копирование для lvalue, одно перемещение для rvalue.•Применение универсальной ссылки. Как и в случае перегрузки, аргумент вы­зывающей функции связан со ссылкой n e w N a m e . Эта операция бесплатна.284Глава 8. ТонкостиБлагодаря использованию std : : forward lvalue-apryмeнты std : : s t ring копируют­ся в Widget : : names , в то время как rvalue-apryмeнты s t d : : st ring перемещаются.Итоговая стоимость для аргументов std : : st r i ng такая же, как и при перегрузке:одно копирование для lvalue, одно перемещение для rvalue.В разделе 5.3 поясняется, что если вызывающая фун кция передает аргумент,отличный от std : : s t r i ng, он будет передан в конструктор std : : s t r i ng, и этоможет привести к нулевому количеству копирований и перемещений std : : s t r ing.Так им образом, функции, получающие универсал ьные ссылки, оказываютсяуникально эффективными.

Однако это не влияет на выполняемый нами анализ, такчто для простоты мы будем предполагать, что вызывающая функция всегда передаетаргументы std : : string.•Независимо от передачи lvalue или rvalue должен быть скон­струирован параметр newName. Если передано lvalue, это стоит одно копирование,если передано rvalue - одно перемещение. В теле функции newName безусловноперемещается в Widget : : names. Итоговая стоимость, таким образом, равна одномукопированию и одному перемещению для lvalue и двум перемещениям для rvalue.По сравнению с подходом с передачей ссылки мы получаем одно лишнее перемеще­ние как для lvalue, так и для rvalue.Передача по значению.Взглянем еще раз на название раздела:Рассмотрите передачу по значению для копируемых па раметров, которые легко пере­мещаются и всегда копируются.Оно сформулировано таким образом не без причины.

Точнее, не без четырех причин.l. Вы должны всего лишь рассмотреть использование передачи по значению. Да,при этом требуется написать всего лишь одну функцию. Да, при этом в объект­ном коде генерируется только одна функция. Да, вы избегаете проблем, связанныхс применением универсальных ссылок. Но стоимость этого решения выше, чемстоимость альтернативных вариантов, и, как вы увидите далее, в некоторых случа­ях есть стоимость, которую мы еще не рассматривали.2. Рассмотрите передачу по значению только для копируемых параметров.

Параме­тры, не соответствующие этому условию, должны иметь типы, являющиеся толь­ко перемещаемыми, поскольку если они не копируемые, а функция всегда делаеткопию, такая копия должна создаваться с помощью перемещающего конструкто­ра2. Вспомним, что преимущества передачи по значению перед перегрузкой за­ключаются в том, что при передаче по значению достаточно написать только однуфункцию.

Но для только перемещаемых типов нет необходимости предоставлятьперегрузку для lvalue, поскольку копирование lvalue влечет вызов копирующегоконструктора, который у таких типов отсутствует. Это означает, что требуется2 Для таких предложений хорошо бы иметь терминологию, отничающую копирование с помощьюкопирующего конструктора от копирования с помощью перемещающего конструктора.8 . 1 . Рассмотрите передачу по значению дпя копируемых параметров....285поддержка только аргументов, являющихся rvalue, и в таком случае решение на ос­нове "переrрузки" требует только одну переrрузку, принимающую rvalue-ccылкy.Рассмотрим класс с данными-членом std : : un ique_pt r<std : : st ring> и функциюустановки для неrо. Тип std : : unique _ptr является только перемещаемым типом,так что подход с использованием "перегрузки" состоит из единственной функции.class WidgetpuЫ i c :void set P t r ( std : : unique_ptr<std: : string>&& ptr){ р = std : : move (ptr) ; )private :std: : unique_ptr<std: : string> р ;;)Вызывающая функция может использовать ее следующим образом:Widgetw.w;setPtr ( std: : make_unique<std: : string> ( "Modern с++") ) ;Здесь rvalue std : : unique_ptr<std : : st ring>, возвращаемое из s t d : : make_unique(см.

раздел 4.4), передается по ссылке в setPtr, где оно перемещается в данные­член р. Общая стоимость составляет одно перемещение.Если бы set Ptr принимала параметры по значению,class WidgetpuЫic:void setptr ( std : : шli.que_ptr<std: : string> ptr ){ р = std: :move (ptr) ; ));то тот же вызов создавал бы параметр ptr перемещением, а затем ptr был быперемещен в данные-член р. Общая стоимость составила б ы два перемещения в два раза больше, чем при подходе с "перегрузкой':3.

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

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

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

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