Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 - [54]

Шрифт
Интервал

>auto delInvmt1 = [](Investment* pInvestment)

>{                           // Пользовательский удалитель

> makeLogEntry(pInvestment); // как лямбда-выражение

> delete pInvestment;        // без состояния

>};


>template    // Возвращаемый тип имеет размер

>std::unique_ptr<Investment, // Investment*

>                decltype(delInvmt1)>

>makeInvestment(Ts&&... args);


>void delInvmt2(Investment* pInvestment) // Пользовательский

>{                                       // удалитель как

> makeLogEntry(pInvestment);             // функция

> delete pInvestment;

>}


>template    // Возвращаемый тип имеет размер

>std::unique_ptr<Investment, // Investment* плюс как минимум

>     void (*)(Investment*)> // размер указателя на функцию!

>makeInvestment(Ts&&... params);

Удалители в виде функциональных объектов с большим размером состояния могут привести к значительным размерам объектов >std::unique_ptr. Если вы обнаружите, что пользовательский удалитель делает ваш интеллектуальный указатель >std::unique_ptr неприемлемо большим, вам, вероятно, стоит изменить свой дизайн.

Фабричные функции — не единственный распространенный способ использования >std::unique_ptr. Эти интеллектуальные указатели еще более популярны в качестве механизма реализации идиомы Pimpl (указателя на реализацию). Соответствующий код не сложен, но его рассмотрение отложено до раздела 4.5, посвященного данной теме.

Интеллектуальный указатель >std::unique_ptr имеет две разновидности: одну — для индивидуальных объектов (>std::unique_ptr), а другую — для массивов (>std::unique_ptr). В результате никогда не возникает неясность в том, на какую сущность указывает >std::unique_ptr. API >std::unique_ptr разработан так, чтобы соответствовать используемой разновидности. Например, в случае указателя для одного объекта отсутствует оператор индексирования (>operator[]), в то время как в случае указателя для массива отсутствуют операторы разыменования (>operator* и >operator->).

Существование >std::unique_ptr для массивов должно представлять только интеллектуальный интерес, поскольку >std::array, >std::vector и >std::string почти всегда оказываются лучшим выбором, чем встроенные массивы. Я могу привести только одну ситуацию, когда >std::unique_ptr имеет смысл — при использовании С-образного API, который возвращает встроенный указатель на массив в динамической памяти, которым вы будете владеть.

Интеллектуальный указатель >std::unique_ptr представляет собой способ выражения исключительного владения на С++11, но одной из наиболее привлекательных возможностей является та, что его можно легко и эффективно преобразовать в >std::shared_ptr:

>std::shared_ptr sp = // Конвертация std: :unique_ptr

> makeInvestment( arguments );    // в std::shared_ptr

Это ключевой момент, благодаря которому >std::unique_ptr настолько хорошо подходит для возвращаемого типа фабричных функций. Фабричные функции не могут знать, будет ли вызывающая функция использовать семантику исключительного владения возвращенным объектом или он будет использоваться совместно (т.e. >std::shared_ptr). Возвращая >std::unique_ptr, фабрики предоставляют вызывающим функциям наиболее эффективный интеллектуальный указатель, но не мешают им заменить этот указатель более гибким. (Информация об интеллектуальном указателе >std::shared_ptr приведена в разделе 4.2.)

Следует запомнить

• >std::unique_ptr представляет собой маленький, быстрый, предназначенный только для перемещения интеллектуальный указатель для управления ресурсами с семантикой исключительного владения.

• По умолчанию освобождение ресурсов выполняется с помощью оператора >delete, но могут применяться и пользовательские удалители. Удалители без состояний и указатели на функции в качестве удалителей увеличивают размеры объектов >std::unique_ptr.

• Интеллектуальные указатели >std::unique_ptr легко преобразуются в интеллектуальные указатели >std::shared_ptr.

4.2. Используйте >std::shared_ptr для управления ресурсами путем совместного владения

Программисты на языках программирования со сборкой мусора показывают пальцами на программистов на С++ и смеются над ними, потому что те озабочены предотвращением утечек ресурсов. “Какой примитив! — издеваются они. — Вы что, застряли в 1960-х годах и в Lisp? Управлять временем жизни ресурсов должны машины, а не люди”. Разработчики на С++ не остаются в долгу: “Вы имеете в виду, что единственным ресурсом является память, а время освобождения ресурса должно быть принципиально неопределимо? Спасибо, мы предпочитаем обобщенность и предсказуемость деструкторов!” Впрочем, в нашей браваде есть немного бахвальства. Сборка мусора в действительности достаточно удобна, а управление временем жизни вручную действительно может показаться похожим на создание микросхем памяти из шкуры медведя с помощью каменных ножей. Почему же не получается взять лучшее из двух миров — систему, которая работает автоматически (как сборка мусора) и к тому же применима ко всем ресурсам и имеет предсказуемое время выполнения (подобно деструкторам)?

Интеллектуальный указатель >std::shared_ptr представляет собой способ, которым С++11 объединяет эти два мира. Объект, доступ к которому осуществляется через указатели


Еще от автора Скотт Мейерс
Эффективное использование STL

В этой книге известный автор Скотт Мейерс раскрывает секреты настоящих мастеров, позволяющие добиться максимальной эффективности при работе с библиотекой STL.Во многих книгах описываются возможности STL, но только в этой рассказано о том, как работать с этой библиотекой. Каждый из 50 советов книги подкреплен анализом и убедительными примерами, поэтому читатель не только узнает, как решать ту или иную задачу, но и когда следует выбирать то или иное решение — и почему именно такое.


Как функции, не являющиеся методами, улучшают инкапсуляцию

Когда приходится инкапсулировать, то иногда лучше меньше, чем большеЯ начну со следующего утверждения: Если вы пишете функцию, которая может быть выполнена или как метод класса, или быть внешней по отношению к классу, Вы должны предпочесть ее реализацию без использования метода. Такое решение увеличивает инкапсуляцию класса. Когда Вы думаете об использовании инкапсуляции, Вы должны думать том, чтобы не использовать методы.Удивлены? Читайте дальше.


Рекомендуем почитать
Изучаем Java EE 7

Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)


Платформа J2Me

Эта книга научит вас, как разрабатывать программное обеспечение для платформы J2ME компании «Sun Microsystems». Эта книга придерживается стиля учебного пособия, это не справочное руководство.Цель — дать вам твердую основу в понятиях и техниках, которая даст вам возможность решиться на самостоятельную разработку качественных приложений.


Виртуальная библиотека Delphi

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Обработка баз данных на Visual Basic.NET

Это практическое руководство разработчика программного обеспечения на Visual Basic .NET и ADO.NET, предназначенное для создания приложений баз данных на основе WinForms, Web-форм и Web-служб. В книге описываются практические способы решения задач доступа к данным, с которыми сталкиваются разработчики на Visual Basic .NET в своей повседневной деятельности. Книга начинается с основных сведений о создании баз данных, использовании языка структурированных запросов SQL и системы управления базами данных Microsoft SQL Server 2000.


Исчерпывающее руководство по написанию всплывающих подсказок

В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.


Программное обеспечение встроенных систем. Общие требования к разработке и документированию

Embedded system software. General requirements for development and documentationСтандарт подготовлен в развитие ГОСТ Р ИСО/МЭК 12207-99 «Информационная технология. Процессы жизненного цикла программных средств» с целью учета специфики разработки и документирования программного обеспечения встроенных систем реального времени.