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

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

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

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

Указатели с исключительным владением не используют управля­ющие блоки, так что н икакого управляющего блока для указываемого объекта несуществует. (Как часть своего построения std : : sha red_pt r осуществляет владе­ние указываемым объектом, так что указатель с исключительным владением ста­новится нулевым.)1 36Гnава 4. Интеnnектуаnьные указатеnи•Когда конструктор std : : sharedytr вызывается с обычным указателем, онЕсли вы хотите создать std : : shared_ptr из объек­та, у которого уже имеется управляющий блок, вы предположительно передаетев качестве аргумента конструктора std : : shared_pt r или std : : weak_ptr (см. раз­дел 4.3), а не обычный указатель. Конструкторы std : : shared_pt r, принимающиев качестве аргументов указатели std : : shared_ptr или std : : weak_pt r, не создаютновые управляющие блоки, поскольку могут воспользоваться управляющими бло­ками, на которые указывают переданные им и нтеллектуальные указатели.создает управляющий блок.Следствием из этих правил является то, что создание более одного std : : shared_ptrиз единственного обычного указателя дает вам бесплатный билет для путешествия в не­определенное поведение, поскольку в результате указываемый объект будет иметь не­сколько управляющих блоков.

Несколько управляющих блоков означают несколько счет­чиков ссылок, а несколько счетчиков ссылок означают, что объект будет удален несколь­ко раз (по одному для каждого счетчика ссылок). И все это значит, что приведенныйниже код плох, ужасен, кошмарен:auto pw=new Widget ;11 pw-обычный указательstd : : shared_ptr<Widget>spwl (pw loggingDe l ) ; / / Создание управляющего блока для *pw,std: : shared_ptr<Widget>/ / Создание второгоspw2 (pw, loggingDe l ) ; / / управляющего блока для *pw !Создание обычного указателя pw, указывающего н а динамически выделенный объ­ект, - плохое решение, поскольку оно противоречит главному совету всей главы: пред­почитайте интеллектуальные указатели обычным указателям. (Если вы забыли, откудавзялся этот совет, заново прочтите первую страницу данной главы.) Но пока что забудемоб этом.

Строка, в которой создается pw, представляет собой стилистическую мерзость,но она по крайней мере не приводит к неопределенному поведению.Далее вызывается конструктор для spwl, которому передается обычный указатель, такчто этот конструктор создает управляющий блок (и тем самым счетчик ссылок) для того,на что он указывает. В данном случае это *pw (т.е. объект, на который указывает pw).Само по себе это не является чем-то страшным, но далее с тем же обычным указателемвызывается конструктор для spw2, и он также создает управляющий блок (а следователь­но, и счетчик ссылок) для *pw. Объект *pw, таким образом, имеет два счетчика ссылок,каждый из которых в конечном итоге примет нулевое значение, и это обязательно приве­дет к попытке уничтожить объект *pw дважды.

Второе уничтожение и будет ответствен­но за неопределенное поведение.Из этого можно вынести как минимум два урока, касающиеся примененияstd : : shared_ptr. Во-первых, пытайтесь избегать передачи обычных указателей конструк­тору std : : shared ptr. Обычной альтернативой этому является применение функцииstd : : make_shared (см. раздел 4.4), но в примере выше мы использовали пользовательские4.2.Используйте std::shared_ptr дл я управления ресурсами путем совместноrо владения1 37удалители, а это невозможно при использовании std : : make_shared. Во-вторых, если вывынуждены передавать обычный указатель конструктору std : : shared_ptr, передавайтенепосредственно результат оператора new, а не используйте переменную в качестве по­средника.

Если первую часть кода переписать следующим образом,s td : : shared_ptr<Widget>spwl (new Widget, / / Непосредственное использование newloggingDel) ;то окажется гораздо труднее создать второй std : : shared_ptr из того же обычного ука­зателя. Вместо этого автор кода, создающего spw2, естественно, будет использовать в ка­честве аргумента инициализации spwl (т.е. будет вызывать копирующий конструкторs t d : : shared_pt r), и это не будет вести ни к каким проблемам:std : : shared_ptr<Widget>spw2 ( spwl ) ;11 spw2 использует тот же/ / управляющий блок, что и spwlОсобенно удивительный способ, которым применение переменных с обычными ука­зателями в качестве аргументов конструкторов std : : shared_pt r может привести к мно­жественным управляющим блокам, включает указатель t h i s .

Предположим, что нашапрограмма использует указатели std : : shared_pt r для управления объектами Widget и унас есть структура данных, которая отслеживает объекты Widget, которые были обрабо­таны:std : : vector<std: : shared_ytr<Widget>> p roce ss edWidget s ;Далее, предположим, что Widget имеет функцию-член, выполняющую эту обработку:class WidgetpuЫic :void process ( ) ;};Вот вполне разумно выглядящий подход к написанию Widget : : process:void Widget : : process ( ){1 1 Обработка WidgetprocessedWidgets . emplace_back (this) ; / / Добавление в список/ / обработанных Widge t ;1 1 это неправильно !Комментарий о неправильности кода относится не к использованию empl ace_back,а к передаче t h i s в качестве аргумента.

(Если вы не знакомы с emp l ace_back, обрати­тесь к разделу 8.2.) Этот код будет компилироваться, но он передает обычный указатель(this) контейнеру указателей std : : shared_ptr. Конструируемый таким образом ука­затель std : : shared_pt r будет создавать новый управляющий блок для указываемого1 38Гn ава 4.

Интеnnектуаnьные указатеnиWidget (т.е. для объекта * t h i s). Это не выглядит ужасным до тех пор, пока вы не по­нимаете, что, если имеются указатели std : : shared_ptr вне функции-члена, которые ужеуказывают на этот объект Widget, вам не избежать неопределенного поведения.API s t d : : s ha r e d _pt r включает средство для ситуаций такого рода. Веро­ятно, его имя - наиболее странное среди всех имен стандартной библиотеки:std : : еnаЫе shared_from_ t h i s.

Это шаблон базового класса, который вы наследуете,если хотите, чтобы класс, управляемый указателями s t d : : shared_pt r, был способенбезопасно создавать std : : shared_ptr из указателя this. В нашем примере Widget будетунаследован от std : : еnаЫе_shared_ from_this следующим образом:_class Widget : puЬlic std: : enaЫe_shared_from_this<Widget>puЫic :void process ( ) ;};Как я уже говорил, s t d : : еnаЫе shared_ from_t h i s является шаблоном базовогокласса. Его параметром типа всегда является имя производного класса, так что классWidget порождается от std : : enaЬle shared_ from_ this<Widget>. Если идея произво­дного класса, порожденного от базового класса, шаблонизированного производным, вы­зывает у вас головную боль, попытайтесь об этом не думать.

Этот код совершенно закон­ный, а соответствующий ш аблон проектирования хорошо известен, имеет стандартноеимя, хотя и почти такое же странное, как std : : еnаЫе_shared_ from this. Это имя Странно повторяющийся шаблон ( The Curiously Recurring Teтplate Pattern - CRTP). Есливы хотите узнать о нем побольше, расчехлите свой поисковик, поскольку сейчас мы воз­вращаемся к нашему барану по имени std : : еnаЫе_shared from t h i s.Шаблон s t d : : enaЬ l e_ shared_ from_ this определяет функцию-член, которая создаетstd : : shared_pt r для текущего объекта, но делает это, не дублируя управляющие блоки.Это функция-член shared_from this, и вы должны использовать ее в функциях-членахтогда, когда вам нужен s t d : : shared_ptr, который указывает на тот же объект, что и ука­затель this. Вот как выглядит безопасная реализация W idget : : p rocess:_____void Widget : : process ( ){/ / Как и ранее , обработка Widget/ / Добавляем std : : shared_ptr, указывающий на/ / текущий объект, в processedWidgetsprocessedWidgets .

emplace_back ( shared_from_this ( ) ) ;Внутри себя shared_ from_this ищет управляющий блок текущего объекта и создаетновый std: : shared ptr, который использует этот управляющий блок. Дизайн функцииполагается на тот факт, что текущий объект имеет связанный с ним управляющий блок.Чтобы это было так, должен иметься уже существующий указатель std : : sha red_p t r4 .2. Испоnьзуйте std::shared_ptr дnя управnения ресурсами путем совместного впадения1 39(например, за пределами функции-члена, вызывающей shared from this ) , который ука­зывает на текущий объект.

Если такого s t d : : shared_ptr нет (т.е. если текущий объектне имеет связанного с н им управляющего блока), результатом будет неопределенное по­ведение, хотя обычно shared_ from_this генерирует исключение.Чтобы препятствовать клиентам вызывать функции-члены, в которых используетсяsha red_from_this, до того как на объект будет указывать указатель s t d : : shared_ptr,классы, наследуемые от std : : enaЫe_ shared_ from_t h i s , часто объявляют свои кон­структоры как pri vate и заставляют клиентов создавать объекты путем вызова фабрич­ных функций, которые возвращают указатели std : : shared_ptr.

Например, класс Widgetможет выглядеть следующим образом:class Widge t : puЬ l i c std: : enaЬle_shared_ from_this<Widget>puЬlic :11 Фабричная функция, пересылающая11 аргументы закрытому конструктору :teшplate<t:ypename . . . Ts>static std: : shared_ytr<Widget> create (Ts&& . . . params) ;void process ( ) ;11Как и ранее11Конструкторыprivate :1;В настоящее время вы можете только смутно припоминать, что наше обсуждениеуправляющих блоков было мотивировано желанием понять, с какими затратами связаноприменение s t d : : shared_ptr. Теперь, когда мы понимаем, как избегать создания слиш­ком большого количества управляющих блоков, вернемся к нашей первоначальной теме.Управляющий блок обычно имеет размер в несколько слов, хотя пользовательскиеудалители и распределители памяти могут его увеличить. Обычная реализация управ­ляющего блока оказывается более интеллектуальной, чем можно было бы ожидать.

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

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

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

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