Эффективный и современный С++. 42 рекомендации по использованию С++11 и С++14 - [129]
Откровенно говоря, вы в любом случае не должны передавать выражения наподобие “>new Widget
” в функции >emplace_back
и >push_back
, как и в большинство любых других функций, поскольку, как поясняется в разделе 4.4, это ведет к возможным проблемам с безопасностью исключений, одну из которых мы только что рассмотрели. Для предотвращения неприятностей требуется, чтобы получение указателя от “>new Widget
” и превращение его в управляющий ресурсом объект выполнялось в одной инструкции, а уже затем этот объект передавался как rvalue функции, которой вы хотели изначально передавать “>new Widget
”. (Более детально этот подход рассматривается в разделе 4.4.) Таким образом, код, использующий >push_back
, должен быть записан скорее как
>std::shared_ptr
> killWidget); // передача его spw
>ptrs.push_back(std::move(spw)); // Добавление spw
> // как rvalue
Версия с использованием >emplace_back
аналогична:
>std::shared_ptr
>ptrs.emplace_back(std::move(spw));
В любом случае данный подход включает стоимость создания и удаления >spw
. С учетом того, что мотивацией для применения функций размещения вместо функций вставки является устранение стоимости создания и уничтожения временного объекта типа, хранящегося в контейнере (а >spw
концептуально и является таким объектом), функции размещения вряд ли превзойдут функции вставки при добавлении в контейнер объектов, управляющих ресурсами (если вы будете следовать хорошо проверенной практике и гарантировать, что между захватом ресурса и превращением его в управляющий объект не будет выполняться никаких действий).
Вторым важным аспектом функций размещения является их взаимодействие с конструкторами, объявленными как >explicit
. Предположим, что вы создаете контейнер объектов регулярных выражений С++11:
>std::vector
Отвлекшись на ссору ваших коллег о том, как часто следует проверять свой Facebook, вы случайно написали следующий, казалось бы, бессмысленный код:
>regexes.emplace_back(nullptr);
Вы не заметили ошибку при вводе, компилятор скомпилировал его без замечаний, так что вам пришлось потратить немало времени на отладку. В какой-то момент вы обнаружили, что вставляете в контейнер регулярных выражений нулевой указатель. Но как это возможно? Указатели не являются регулярными выражениями, и если вы попытаетесь написать что-то вроде
>std::regex r = nullptr;// Ошибка! Не компилируется!
компилятор отвергнет такой код. Интересно, что будет отвергнут и вызов >push_back
вместо >emplace_back
:
>regexes.push_back(nullptr); // Ошибка! Не компилируется!
Такое любопытное поведение поясняется тем, что объекты >std::regex
могут быть построены из символьных строк. Это делает корректным такой полезный код, как
>std::regex upperCaseWord("[A-Z]+");
Создание >std::regex
из символьной строки может иметь достаточно высокую стоимость, так что для минимизации вероятности непреднамеренных расходов конструктор >std::regex
, принимающий указатель >const char*
, объявлен как >explicit
. Именно поэтому не компилируются следующие строки:
>std::regex r = nullptr; // Ошибка! Не компилируется!
>regexes.push_back(nullptr); // Ошибка! Не компилируется!
В обоих случаях требуется неявное преобразование указателя в >std::regex
, а объявление конструктора как >explicit
его предотвращает.
Однако в вызове >emplace_back
мы передаем не объект >std::regex
, а аргументы конструктора объекта >std::regex
. Это не рассматривается как запрос неявного преобразования. Компилятор трактует этот код так, как если бы вы написали
>std::regex r(nullptr); // Компилируется
Если лаконичный комментарий “Компилируется” кажется вам лишенным энтузиазма, то это хорошо, потому что, несмотря на компилируемость, данный код имеет неопределенное поведение. Конструктор >std::regex
, принимающий указатель >const char*
, требует, чтобы этот указатель был ненулевым, а nullptr подчеркнуто нарушает данное требование. Если вы напишете и скомпилируете такой код, лучшее, на что вы можете надеяться, — аварийное завершение программы во время выполнения. Если вы не такой счастливчик, то вам предстоит получить немалый опыт работы с отладчиком.
На минутку оставляя без внимания >push_back
и >emplace_back
, обратим внимание на то, что очень похожие синтаксисы инициализации дают совершенно разные результаты:
>std::regex r1 = nullptr; // Ошибка! Не компилируется
>std::regex r2
В этой книге известный автор Скотт Мейерс раскрывает секреты настоящих мастеров, позволяющие добиться максимальной эффективности при работе с библиотекой STL.Во многих книгах описываются возможности STL, но только в этой рассказано о том, как работать с этой библиотекой. Каждый из 50 советов книги подкреплен анализом и убедительными примерами, поэтому читатель не только узнает, как решать ту или иную задачу, но и когда следует выбирать то или иное решение — и почему именно такое.
Когда приходится инкапсулировать, то иногда лучше меньше, чем большеЯ начну со следующего утверждения: Если вы пишете функцию, которая может быть выполнена или как метод класса, или быть внешней по отношению к классу, Вы должны предпочесть ее реализацию без использования метода. Такое решение увеличивает инкапсуляцию класса. Когда Вы думаете об использовании инкапсуляции, Вы должны думать том, чтобы не использовать методы.Удивлены? Читайте дальше.
Java Enterprise Edition (Java EE) остается одной из ведущих технологий и платформ на основе Java. Данная книга представляет собой логичное пошаговое руководство, в котором подробно описаны многие спецификации и эталонные реализации Java EE 7. Работа с ними продемонстрирована на практических примерах. В этом фундаментальном издании также используется новейшая версия инструмента GlassFish, предназначенного для развертывания и администрирования примеров кода. Книга написана ведущим специалистом по обработке запросов на спецификацию Java EE, членом наблюдательного совета организации Java Community Process (JCP)
Эта книга научит вас, как разрабатывать программное обеспечение для платформы J2ME компании «Sun Microsystems». Эта книга придерживается стиля учебного пособия, это не справочное руководство.Цель — дать вам твердую основу в понятиях и техниках, которая даст вам возможность решиться на самостоятельную разработку качественных приложений.
В книге рассказывается история главного героя, который сталкивается с различными проблемами и препятствиями на протяжении всего своего путешествия. По пути он встречает множество второстепенных персонажей, которые играют важные роли в истории. Благодаря опыту главного героя книга исследует такие темы, как любовь, потеря, надежда и стойкость. По мере того, как главный герой преодолевает свои трудности, он усваивает ценные уроки жизни и растет как личность.
Это практическое руководство разработчика программного обеспечения на 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 «Информационная технология. Процессы жизненного цикла программных средств» с целью учета специфики разработки и документирования программного обеспечения встроенных систем реального времени.