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

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

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

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

1 и 4.2), в то время как конструкторы s t d : : uni que _pt rи std : : shared_pt r это позволяют. Для данного пользовательского удалителя Widgetauto widgetDeleter=[ ] ( Widget* pw) {_);создание интеллектуального указателя с применением оператора new является оченьпростым:std : : unique ptr<Widget, decltype (widgetDeleter) >upw (new Widget, widgetDeleter) ;std : : shared_ptr<Widget> spw (new Widget, widgetDeleter ) ;Сделать то же самое с помощью mаkе-функции невозможно.Второе ограничение на mаkе-функции проистекает из синтаксических деталей ихреализации. В разделе 3 .

1 поясняется, что при создании объекта, тип которого пере­гружает конструкторы как с параметрами s t d : : i n i t i a l i ze r_l i s t , так и без них,создание объекта с использованием фигурных скобок предпочитает конструкторs td : : i n i t i a l i zer_l i s t , в то время как создание объекта с использованием круглыхскобок вызывает конструктор, у которого нет параметров std : : ini t i a l i zer_ l i st. mаkе­функции выполняют прямую передачу своих параметров конструктору объекта, но де­лается ли это с помощью круглых или фигурных скобок? Для некоторых типов ответна этот вопрос очень важен. Например, в вызовахauto upvauto spvstd : :make_unique<std : : vector<int>> ( l O, 2 0 ) ;std : :make_shared<std: : vector<int>> ( l O, 2 0 ) ;результирующие интеллектуальные указатели должны указывать на векторы std : : vectorс 10 элементами, значение каждого из которых - 20, или на векторы с двумя элементами,один со значением 10, а второй со значением 20? Или результат непредсказуем?1 50Глава 4.

Интеллектуальные указателиХорошая новость в том, что результат все же предсказуем: оба вызова создают векто­ры std : : vector с 10 элементами, значение каждого из которых равно 20. Это означаетчто в mаkе-функциях прямая передача использует круглые, а не фигурные скобки. Плохаяновость в том, что если вы хотите создавать свои указываемые объекты с помощью ини­циализаторов в фигурных скобках, то должны использовать оператор new непосредствен­но.

Использование mаkе-функции требует способности прямой передачи инициализаторав фигурных скобках, но, как поясняется в разделе 5.8, такие инициализаторы не могут бытьпереданы прямо. Однако в разделе 5.8 описывается и обходной путь: использование выводатипа auto для создания объекта std : : ini t ia l i zer_ l is t из инициализатора в фигурныхскобках (см.

раздел 1 .2) с последующей передачей созданного объекта через mаkе-функцию:11Создание std: : initiali zer_listauto initList = { 10 , 20 } ;11Создание std : : vector с помощью конструкторас параметром std : : initial i zer_l istauto spvstd : : ma ke_shared<std : : vector<int» ( initList) ;11=Для std : : unique _p t r эти два сценария (пользовательские удалители и фигурныеинициализаторы) являются единственными, когда применение mаkе-функции оказывает­ся проблематичным.

Что касается s t d : : shared_pt r и его mаkе-функций, то есть еще двасценария. Оба они являются крайними случаями, но некоторые разработчики постоянноходят по краю, и вы можете быть одним из них.Некоторые классы определяют собственные версии operator new и operator de lete.Наличие этих функций подразумевает, что глобальные функции выделения и освобож­дения памяти для объектов этого типа являются неприемлемыми. Зачастую подпрограм­мы для конкретных классов разрабатываются только для выделения и освобожденияблоков памяти, по размеру точно совпадающих с размером объектов класса; например,ope rator new и operator delete для класса Widget зачатую способны выделять и ос­вобождать только блоки памяти размером s i zeof ( W i dget ) .

Такие подпрограммы пло­хо подходят для поддержки пользовательского распределения памяти для указателейstd : : shared _ptr (с помощью s t d : : a l locate _shared) и их удаления (с помощью поль­зовательских удалителей), поскольку количество запрашиваемой s t d : : а llocate_sharedпамяти не совпадает с размером динамически создаваемого объекта (который равенразмеру этого объекта плюс размер управляющего блока). Соответственно, применениеmаkе-функций для создания объектов типов со специфичными для данного класса верси­ями operator new и operator delete обычно является плохой идеей.Преимущества размера и скорости функции s t d : : ma ke_shared по сравнению с не­посредственным применением оператора new вытекают из того факта, что управляющийблок указателя std : : shared_ptr размещается в том же блоке памяти, что и управляемыйобъект.

Когда счетчик ссылок объекта становится равным нулю, объект уничтожается(т.е. вызывается его деструктор). Однако занятая им память не может быть освобожденадо тех пор, пока не будет уничтожен и управляющий блок, поскольку блок динамическивыделенной памяти содержит как объект, так и управляющий блок.4.4. П редпочитайте использование std::make_uпique и std::make_shared....151Как я уже отмечал, управляющий блок содержит, помимо самого счетчика ссылок,некоторую учетную информацию. Счетчик ссылок отслеживает, сколько указателейs t d : : shared_pt r ссылаются на управляющий блок, но управляющий блок содержити второй счетчик ссылок, который подсчитывает, сколько указателей std : : weak_ptrссылаются на этот управляющий блок. Этот второй счетчик ссылок известен как слабыйсчетчик ( weak couпt)4• Когда указатель std : : weak_pt r проверяет, не является ли он про­сроченным (см.

раздел 4.2), он делает это путем обращения к счетчику ссылок (но нек слабому счетчику) в управляющем блоке, на который ссылается. Если счетчик ссылокравен нулю (т.е. если указываемый объект не имеет указателей std : : shared_ptr, указы­вающих на него, и, таким образом, является удаленным), указатель std : : weak_ptr явля­ется просроченным. В противном случае он просроченным не является.Пока указатели std : : wea k_pt r указывают на управляющий блок (т.е. слабый счет­чик больше нуля), этот управляющий блок должен продолжать существовать. А покасуществует управляющий блок, память, его содержащая, должна оставаться выделен­ной.

Таким образом, память, выделенная mаkе-функцией для std : : shared_pt r не мо­жет быть освобождена до тех пор, пока не будут уничтожены последний указательstd : : shared_ptr и последний указатель std : : weak_ptr, ссылающиеся на объект.Если время между уничтожением последнего s t d : : s ha re d_pt r и последнегоs t d : : weak_pt r значительно, между уничтожением объекта и занимаемой им памятьюможет происходить задержка, что особенно важно для типов с большим размером:class ReallyBigType {auto pBigObj...1;=11 Создание большогоstd: :make_shared<ReallyBigType> ( ) ; / / объекта с помощью/ / s t d : : make shared/ / Создание указателей std: : shared_ptr и s t d : : weak_ptr// на большой объект и работа с ними/ / Уничтожение последнего указателя std : : shared_ptr на/ / этот объект; остаются указатели s t d : : weak_ptr/ / Во время этого периода память , ранее занятая большим11 объектом, остается занятой11 Уничтожение последнего указателя s td : : wea k_ptr на/ / объект; освобождение памяти, выделенной для/ / управляющего блока и объекта4На практике значение слабого счетчика не всегда совпадает с количеством указателей std : :weak pt r, ссылающихся на управляющий блок, поскольку разработчики библиотеки нашли спосо­бы добавлять о слабый счетчик дополнительную информацию, которая упрощает генерацию лучшегокода.

В данном разделе мы игнорируем этот факт и считаем, что значение слабого счетчика представ­ляет собой количество указателей std : : weak_ptr, ссынающихся на управняющий блок.j).1 52Глава 4. И нтеллектуальные указателиПри непосредственном использовании пеw память для объекта Rea l l yBigType можетбыть освобождена, как только уничтожается последний указатель s t d : : shared_ptr, ука­зывающий на него:class ReallyBigType {11 Как и ранее};/ / Создание очень большого объекта с помощью пew : s t d : : sharedptr<Real lyBigType> pBigObj (new ReallyBigType ) ;...1 1 Как и ранее, создание указателей std : : shared_ptr и11 std : : weak_ptr на объект и работа с ними11 Уничтожение последнего указателя std: : shared ptr на11 этот объект; остаются указатели std : : weak_ptr11 Память , выделенная для объекта, освобождается/ / Во время этого периода остается занятой только память ,/ / ранее выделенная для управляющего блока11 Уничтожение последнего указателя std : : weak_ptr на11 объект; освобождение памяти , выделенной для11 управляющего блокаОказавшись в ситуации, когда использование функции std : : make_shared невозможноили неприемлемо, вы можете захотеть защититься от ранее рассматривавшихся намипроблем, связанных с безопасностью исключений.

Лучший способ сделать это - обес­печить немедленную передачу результата операции пеw конструктору интеллектуально­го указателя в инструкции, которая не делает ничего иного. Это предотвратит созданиекомпилятором кода, который может генерировать исключение между оператором пеwи вызовом конструктора интеллектуального указателя, который будет управлять объек­том, созданным оператором new.В качестве примера рассмотрим небольшое изменение небезопасного с точки зренияисключений вызова функции p rocesswidget, которую мы рассматривали ранее. В этотраз мы укажем пользовательский удалитель:void processwidget ( s td : : shared_ptr<Widget> spw, / / Как и ранееiпt priorit y ) ;void cusDel (Widget •ptr ) ;1 1 Пользовательский удалительВот небезопасный с точки зрения исключений вызов:processWidget (11std : : shared_ptr<Widget> ( пew Widge t , cusDel ) , / /computePriority ( )11);11Как и ранее,потенциальнаяутечкаресурса !4.4.

П редпочитайте испоnьэование std::make_unique и std::make_shared""1 53Вспомним: если computePriority вызывается после new W idget, но до конструктораstd : : shared_ptr и если compute Priority генерирует исключение, происходит утечкадинамически созданного Widget.Здесь применение пользовательского удалителя препятствует использованиюstd : : ma ke_shared, так что избежать проблемы можно, поместив создание Widget в ди­намической памяти и конструирование std : : shared_pt r в собственную инструкцию,а затем вызвав функцию processWidget с передачей ей полученного std : : shared ptr.Вот и вся суть этого метода, хотя, как мы вскоре увидим, его можно подкорректироватьдля повышения производительности:std : : shared_ptr<Widget> spw ( new Widget , cusDel ) ;processWidget ( spw, computePriorit y ( ) ) ; / / Корректно, но не/ / оптимально ; см.

нижеЭтот код работает, поскольку std : : shared_ptr предполагает владение обычным ука­зателем, переданным конструктору, даже если этот конструктор генерирует исключение.В данном примере, если конструктор spw генерирует исключение (например, из-за невоз­можности выделить динамическую память для управляющего блока), он все равно га­рантирует вызов cusDel для указателя, полученного в результате операции new Widget.Небольшое снижение производительности возникает из-за того, что в небезопасномс точки зрения исключений коде мы передавали функции processWidget rvalueprocessWidget (std: : shared_ptr<Widget> (new Widget, cusDel) , 1 1 rvaluecornputePriori ty ( ));а в случае безопасного вызова - передаем lvalue:processWidget ( spw, computePriori ty ( ) ) ;1 1 lvalueПоскольку параметр std : : shared ptr функции processWidget передается по значе­н ию, создание из rvalue влечет за собой только перемещение, в то время как созданиеиз lvalue требует копирования.

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

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

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

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