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

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

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

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

Этоотличие позволяет функциям размещения избегать создания и уничтожения временныхобъектов, которые могут требоваться функциям вставки.Поскольку функции размещения может быть передан аргумент типа, хранимогов контейнере (аргумент, таким образом, заставляет функцию выполнить копирующееили перемещающее конструирование), размещение может использоваться даже тогда,когда функция вставки не требует временного объекта. В таком случае вставка и разме­щение делают, по сути, одно и то же. Например, дляstd: : str i n g queenOfDisco ( " Donna Summe r " ) ;оба приведенных далее вызова корректны, и оба приводят к одному и тому же резуль­тату:vs .

push_Ьack ( queenOfDisco ) ;11 Копирующее конструирование//vs . emplace_Ьack ( queenOfDisco ) ;queenOfDiscoв концеvs11 То же самоеТаким образом, размещающие функции могут делать все то же самое, что и функциивставки. И ногда они делают это более эффективно и как минимум теоретически недолжны делать менее эффективно. Так почему же мы не используем их все время?8.2. Рассмотрите п рименение размещения вместо вставки293Потому что теоретически разницы между теорией и практикой нет, а практически есть. При текущих реализациях стандартной библиотеки имеются ситуации, когда, каки ожидается, размещение превосходит вставку, но - увы! - есть ситуации, когда встав­ка работает быстрее. Такие ситуации непросто охарактеризовать, поскольку они зависятот типов передаваемых аргументов, используемых контейнеров, местоположения вставкиили размещения в контейнере, безопасности исключений конструкторов типов, содержа­щихся в контейнере, и для контейнеров, в которых запрещены дубликаты (т.е.

std : : set,std : : map, std : : unordered_ set, std : : unordered_map) , от того, содержится ли уже в кон­тейнере вставляемое значение. А потому следует пользоваться обычным советом по по­вышению производительности: для определения того, какой метод работает быстрее,надо сравнивать их реальную производительность в конкретных условиях.Это, конечно, не очень приятно, так что вы будете рады узнать, что есть эвристи­ческий алгоритм, который может помочь вам определить ситуации, когда, скорее всего,имеет смысл использовать функции размещения.

Если все приведенные далее утвержде­ния справедливы, размещение почти наверняка будет опережать вставку.•При­мер, с которого начат данный раздел (добавление s t d : : s t r i ng со значением"x y z z y " в std : : vector vs), демонстрирует значение, добавляемое в конец вектораvsв место, где пока что нет никакого объекта. Таким образом, новое значениедолжно быть сконструировано в std : : vector. Если мы пересмотрим пример так,что новая строка std : : st ring будет направляться в местоположение, уже занятоеобъектом, это будет совсем другая история:Добавляемое значение конструируется в контейнере, а не присваивается.-std: : vector<std : : string> vs ;11 Как и ранее11 Добавление элементов в vsvs .

emplace (vs . Ьegin ( ) , "xyzzy" ) ; // Добавление "xyzzy" в начало vsПри таком коде только редкие реализации будут конструировать добавляемыйобъект std : : st ring в памяти, занятой vs [ О ] . Большинство реализаций используютперемещающее присваивание в указанное место. Но перемещающее присваиваниетребует наличия перемещаемого объекта, а это означает, что необходимо созданиевременного объекта. Поскольку основное преимущество размещения над вставкойзаключается в том, что не создаются и не уничтожаются временные объекты,при добавлении значения в контейнер с помощью присваивания преимуществаразмещения исчезают.Увы, выполняется ли добавление значения в контейнер путем конструирования илиперемещения, в общем случае зависит от реализации.

И вновь на помощь можетприйти эвристика.Контейнеры на основе узлов почти всегда используют для добавления новых значенийконструирование, а большинство стандартных контейнеров я вляются именнотаковыми. Исключениями являются s t d : : vect or, s t d : : de que и s t d : : s t r i n g .(Контейнер s t d : : a r r a y также не является таковым, но он не поддерживаетн и вставку, ни размещение, поэтому упоми нать о нем здесь нет смысла.) Вконтейнерах, не основанных на узлах, можно рассчитывать на использование294Глава 8. Тонкостифункцией emplace back для размещения нового значения конструирования вместоприсваивания; то же самое можно сказать и о функции emplace_ f ront контейнераstd : : deque.•Типы передаваемых аргументов отличаются от типа, хранящеrося в контейнере.И вновь, преимущество размещения по сравнению со вставкой в общем случае свя­зано с тем фактом, что его интерфейс не требует создания и уничтожения времен­ного объекта при передаче аргументов типа, отличного от типа, хранящегося в кон­тейнере.

Когда в контейнер c on t a i n e r<T> добавляется объект типа Т, нет причиножидать, что размещение окажется быстрее вставки, поскольку для удовлетворенияинтерфейсу вставки не требуется создание временного объекта.•Маловероятно, что контейнер отверrнет новое значение как дубликат. Это озна­чает, что либо контейнер разрешает наличие дубликатов, либо большинство переда­ваемых значений уникальны. Это важно, поскольку для того, чтобы определить на­личие дубликата, реализации размещения обычно создают узел с новым значением,а затем сравнивают его с имеющимися узлами контейнера. Если добавляемое зна­чение в контейнере отсутствует, узел встраивается в контейнер.

Однако, если такоезначение уже есть в контейнере, размещение прерывается, а узел уничтожается, такчто впустую расходуется стоимость создания и уничтожения объекта. Такие узлыдля функций размещения создаются более часто, чем для функций вставки.Приведенные вызовы, с которыми мы уже сталкивались в данном разделе, удовлетво­ряют всем перечисленным критериям. Они работают быстрее соответствующих вызововpush_back.vs . emplace_back ( "xyzzy" ) ; //////11vs . emplace_back ( SO , ' х ' ) ; 11Конструирует новое значение в концеконтейнера ; тип аргумента отличен оттипа, хранимого в контейнере ;контейнер не отвергает дубликатыТо же самоеПри принятии решения об использовании функций размещения стоит иметь в видуеще пару вопросов.

Первый из них связан с управлением ресурсами. Предположим, чтоу вас есть контейнер с объектами s t d : : shared_pt r <Widget>std: : list<std : : shared_ptr<Widget>> ptr s ;и в ы хотите добавить s t d : : sha red_ptr, который должен быть освобожден с помощьюпользовательского удалителя (см. раздел 4.2). В разделе 4.4 поясняется, что по возможно­сти вы должны использовать для создания std : : shared _ptr функцию s t d : : make_shared,но в нем же указано, что существуют ситуации, когда это невозможно. Одна из такихситуаций - когда вы хотите указать пользовательский удалитель.

В этом случае для по­лучения обычного указателя, которым будет управлять интеллектуальный указательstd : : shared_pt r, вы должны непосредственно использовать оператор new.Если пользовательский удалитель представляет собой функциюvoid kil lWidget (Widget * pWidget ) ;8.2. Рассмотрите п рименение размещения вместо вставки295то код, использующий фун кцию вставки, может выглядеть следующим образом:ptrs .push_Ьack ( std : : shared_ptr<Widget> ( new Widge t , kil lWidge t ) ) ;Он может также принять и такой вид, означающий то же самое:ptrs .push_Ьack ( { new Widge t , killWidget } ) ;В любом случае перед вызовом p u s h _b a c k будет создан времен ный объектstd : : sha red_pt r.

Параметром push_back является ссылка на s t d : : shared_pt r, так чтодолжен быть объект, на который ссылается этот параметр.Фун кция e m p l a c e _ b a c k должна избегать создания временного объектаs t d : : s hared_ptr, но в этом случае ценность временного объекта гораздо выше его стои­мости. Рассмотрим следующую потенциальную последовательность событий.1. В любом из приведенных выше вызовов конструируется временный объектstd : : shared_pt r<Widget >, хранящий простой указатель, являющийся результа­том операции "new Widget': Назовем этот объект t emp.2. Функция push_b a c k получает t emp по ссылке. В процессе выделения памятидля узла списка, который должен содержать копию t emp, генерируется исключе­ние нехватки памяти.3. При выходе исключения за пределы push_back объект t emp уничтожается. По­скольку это единственный интеллектуальный указатель std : : sha red_pt r, указы­вающий на управляемый им объект W idget, он автоматически удаляет последний,в данном случае с помощью вызова ki l lWidget.Несмотря на происшедшую генерацию исключения нет никаких утечек: Widget, соз­данный с помощью " new Widget" в вызове push_back, освобождается деструктором объ­екта std : : sha red_pt r, который был создан для управления им (объектом t emp).

Все от­лично.Рассмотрим теперь, что произойдет при вызове emplace _back вместо push_back:ptrs . emplace_Ьack ( new Widge t , killWidget ) ;1 . Обычный указатель, являющийся результатом выполнения "new Widget", переда­ется с помощью прямой передачи в точку внутри emp l ace back, где выделяетсяпамять для узла списка. При попытке выделения памяти генерируется исключениенехватки памяти._2. При выходе исключения за пределы emp l a ce _back обычный указатель, которыйбыл единственным средством доступа к W idget в динамической памяти, оказыва­ется потерянным. Происходит утечка W idget (и всех ресурсов, которыми владеетэтот объект).В этом сценарии все совсем не отлично, и класс s t d : : s ha red_pt r в этом не пови­нен.

Та же самая проблема возникнет при использовании s t d : : u n i que_pt r с пользо­вательским удалителем. По существу, эффективность классов управления ресурсами,296Гл ава 8. Тонкоститаких как s t d : : shared_ptr и std : : un i que_ptr, основана на немедленной передаче ре­сурсов (таких, как обычные указатели , возвращаемые оператором new) конструкторамуправляющих ресурсами объектов. Тот факт, что функции наподобие std : : make sharedи std : : make_unique автоматизируют этот процесс, является одной из причин, по кото­рым эти функции так важны.В вызовах функций вставки контейнеров, хранящих управляющие ресурсами объек­ты (например, s t d : : l ist<std : : shared_pt r<Widget»), типы параметров функций в об­щем случае гарантируют, что между захватом ресурса (например, использованием опе­ратора new) и конструированием управляющего ресурсом объекта ничего не происходит.В функциях размещения прямая передача откладывает создание управляющих ресурса­ми объектов до тех пор, пока они не смогут быть сконструированы в памяти контейнера,и тем самым открывают окно, генерация исключения в котором может привести к утечкересурсов.

Все стандартные контейнеры подвержены этой проблеме. При работе с кон­тейнерами, хранящими управляющие ресурсами объекты, вы должны принять меры,гарантирующие, что при выборе функции размещения вместо функции вставки вы незаплатите за повышение эффективности безопасностью исключений.Откровенно говоря, вы в любом случае не должны передавать выражения наподобие"new Widget" в функции emplace_back и push_back, как и в большинство любых другихфункций, поскольку, как поясняется в разделе 4.4, это ведет к возможным проблемамс безопасностью исключений, одну из которых мы только что рассмотрели. Для предот­вращения неприятностей требуется, чтобы получение указателя от "new Widget" и пре­вращение его в управляющий ресурсом объект выполнялось в одной инструкции, а ужезатем этот объект передавался как rvalue функции, которой вы хотели изначально пере­давать "new Widget': (Более детально этот подход рассматривается в разделе 4.4.) Такимобразом, код, использующий push_back, должен быть записан скорее какstd: : sha.redytr<Widqet> spw (new Widqet, / / Создание Widget иkillWidqet) ; / / передача его spwpt r s .

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

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

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

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