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

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

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

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

К счастью, этот код легко сделать работающим. Все, чтодля этого требуется, - понимание причины проблемы.Проблема возникает из-за кода, который генерируется при уничтожении w (напри­мер, при выходе переменной за пределы области видимости). В этой точке вызываетсяее деструктор. Если определение класса использует std : : unique_pt r, мы не объявляемдеструктор, так как нам нечего в него поместить.

В соответствии с обычными правиламигенерации специальных функций-членов компиляторами (см. раздел 3.1 1 ) этот деструк­тор создается вместо нас компилятором. В этот деструктор компилятор вносит код вы­зова деструктора члена-данных p impl класса Widget. p impl представляет собой указательstd : : uni que_ptr<Widget : : Impl>, т.е. указатель std : : unique_ptr, использующий удали­тель по умолчанию.

Удалитель по умолчанию является функцией, которая применяетоператор delete к обычному указателю внутри s t d : : unique_pt r. Однако перед тем какиспользовать delete, реализации удалителя по умолчанию в С++ 1 1 обычно применяютstatic_assert, чтобы убедиться, что обычный указатель не указывает на неполный тип.Когда компилятор генерирует код для деструкции Widget w, он в общем случае сталки­вается с неудачным static_assert, что и приводит к выводу сообщения об ошибке.

Этосообщение обычно связано с точкой, в которой происходит уничтожение w, посколькудеструктор Widget, подобно всем генерируемым компиляторами специальным функци­ям-членам, неявно является i n l i ne. Сообщение часто указывает на строку, в которойсоздается w, поскольку она представляет собой исходный текст, явно создающий объект,приводящий впоследствии к неявной деструкции.Для исправления ситуации надо просто обеспечить полноту типа Widget : : Implв точке, где генерируется код, уничтожающий std : : unique_ptr<Widget : : Impl>.

Тип ста­новится полным, когда его определение становится видимым, а Widget : : Impl определенв файле widget . срр. Ключом к успешной компиляции является требование, чтобы ком­пилятор видел тело деструктора Widget (т.е. место, где компилятор будет генерировать1 58Глава 4. Интеллектуальные указателикод для уничтожения члена-данных s td : : unique_pt r) только внутри widget . срр, послеопределения W idget : : Impl.Добиться этого просто.

Объявим деструктор W i dget в w idget h но не будем опреде­лять его там:.,1 1 Как и ранее , в файле "widget . h"class WidgetpuЬl i c :Widget ( ) ;/ / Только объявление-Widget ( ) ;private :11 Как и ранееstruct Impl ;std : : unique_ptr<Impl> pimpl ;};Определим его в widget . срр после определения W idget : : I mp l :# include# include# include# include"widget . h""gadget . h"<string><vector>1 1 Как и ранее, в файле "widget .

cpp"st ruct Widget : : Impl11 Как и ране е , определение/ / Widget : : Implstd : : str ing name ;std : : vector<douЫe> data;Gadget g l , g2, gЗ;};/ / Как и ранееWidget : : W idget ( ): pimpl ( std: : make_unique< Impl> ( ) ){}Widget: : -Widget ()11 Определение -Widget{}Это хорошо работает и требует небольшого набора текста, но если вы хотите подчер­кнуть, что генерируемый компилятором деструктор работает верно, что единственнаяпричина его объявления - генерация его определения в файле реализации W idget, то выможете определить тело деструктора как default :=Widget : : -Widget ( )=default; / / Тот же результат, что и вЬШiеКлассы, использующие идиому Pimpl, являются естественными кандидатами на под­держку перемещения, поскольку генерируемые компилятором операции перемещенияделают именно то, что требуется: выполняют перемещение std : : unique_ptr. Как пояс­няется в разделе 3.

1 1 , объявление деструктора W i dg e t препятствует генерации компи­лятором операций перемещения, так что, если вы хотите обеспечить их поддержку, вы4.5 . При использовании идиомы указате л я на реализацию определяйте специальные ""1 59должны объявить их самостоятельно. Поскольку генерируемые компилятором версииведут себя так, как надо, соблазнительно реализовать их следующим образом:class Widget {puЫ i c :Widget ( ) ;-Widget ( ) ;11 В "widget .

h"// Идея верна ,Widget (Widget&& rhз) = clefault;Widget& operator= (Wiclqet&& rhз) = default; / / код - нет '1 1 Какprivate :struct Imp l ;std : : unique_ptr<Impl> pimpl ;);иранееЭтот подход приводит к тем же проблемам, что и объявление класса без деструктора,и по той же самой причине.

Генерируемый компилятором оператор перемещающегоприсваивания должен уничтожить объект, на который указывает p impl, перед тем какприсвоить указателю новое значение, но в заголовочном файле W i dg e t указатель pimplуказывает на неполный тип. Ситуация отличается для перемещающего конструктора.Проблема в том, что компиляторы обычно генерируют код для уничтожения pimpl в томслучае, когда в перемещающем конструкторе генерируется исключение, а уничтожениеplmpl требует, чтобы тип Impl был полным.Поскольку проблема точно такая же, как и ранее, то и решение ее такое же - переносопределений перемещающих операций в файл реализации:1 1 В файле "widget .

h"class Widget {puЫ i c :Widget ( ) ;-Widget ( ) ;/ / Только объявленияWidget (Widget&& rhз) ;Widget& operator= (Wiclqet&& rhз) ;private :1 1 Как и ранееstruct Imp l ;std : : unique_ptr<Impl> pimpl ;);#include <string>struct Widget : : Impl {11 В файле " widge t . cpp"...1;/ / КакWidget : : Widget ( ) / / as before: pimpl ( std: : ma ke_unique<Impl> ( ) ){)1 60Глава 4. Интеллектуальные указателииранее11 Как и ранееdefault ;Widget : : -Widget ( )11 Определения :Widqet: :Widqet (Widget&& rhs)default ;Widqet& Widqet: : operator= (Widget&& rhs)==default;Идиома Pimpl представляет собой способ снижения зависимости между реализациейкласса и его клиентами, но концептуально идиома не меняет то, что представляет со­бой класс. Исходный класс Widget содержал члены-данные s t d : : s t r i ng, s t d : : ve c t o rи Gadge t , так что в предположении, что объекты Gadg e t , как и объекты s t d : : s t r i пgи std : : vector, могут копироваться, имеет смысл в поддержке классом Widget копирую­щих операций.

Мы должны написать эти функции самостоятельно, поскольку ( 1 ) компи­ляторы не генерируют копирующие операции для классов с типами, поддерживающимитолько перемещение (наподобие s t d : : u n i que_pt r ) и (2) даже если бы они генерирова­лись, то такие функции выполняли бы копирование только указателя s t d : : unique_pt r(т.е. выполняли бы мелкое копирование), а м ы хотим копировать то, н а что указываетэтот указатель (т.е.

выполнять глубокое копирование).В соответствии с ритуалом, который нам теперь хорошо знаком, мы объявляем функ­ции в заголовочном файле и реализуем их в файле реализации:!! В файле "widget . h "cla ss WidgetpuЫ i c :!! Прочее, как ранее11 ТолькоWidqet (const Widqet& rhs) ;Widqet& operator= ( const Widqet& rhs) ; / / объявленияprivate :struct Impl ;std: : unique_ptr<Impl> pimp l ;1;// Как и ранее#include "widget . h "11 В "widget .

cpp"struct Widget : : Impl {Widget : : -Widget ( )=...1;default ;1 1 Как и ранее11 Прочее, как и ранееWidqet : :Widqet ( const Widget& rhs) / / Копирующий конструкторр!шрl (nullptr)std: : make_unique<Iшpl> ( *rhs .piшpl) ;{ if (rhs . piшpl) piшpl=! / Копирующее присваивание :Widqet& Widqet: : operator= (const Widqet& rhs){if ( ! rhs . р!шрl) р!шрl . reset ( ) ;else if ( ! р!шрl) р!шрl = std : : make_unique<Iшpl> ( *rhs .

pimpl ) ;4.5. При испоnьзовании идиомы указатеnя на реализацию определяйте специальные....161else *pimpl = *rhs .pimpl ;return *this ;Реализация достаточно проста, хотя мы и должны обрабатывать случаи, в которых па­раметр rhs или, в случае копирующего оператора присваивания, *this был перемещен,а потому содержит нулевой указатель pimpl. В общем случае мы используем тот факт,что компиляторы создают копирующие операции для Impl, и эти операции копируюткаждое поле автоматически. Так что мы реализуем копирующие операции Widget путемвызова копирующих операций Widget : : Impl, сгенерированных компилятором.

В обеихфункциях обратите внимание, как мы следуем совету из раздела 4.4 предпочитать при­менение std : : make_unique непосредственной работе с new.При реализации идиомы Pimpl используемым интеллектуальным указателем являетсяstd : : unique_pt r, поскольку указатель p impl внутри объекта (например, внутри Widget )имеет исключительное владение соответствующим объектом реализации (например,объектом Widget : : Imp l ) . Интересно также отметить, что если бы мы использовалидля p impl указатель s t d : : shared_pt r вместо s t d : : unique_pt r (т.е.

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

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

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

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