![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
Annex: AlternativesBoost , Chapter 1. Boost.LocalFunction 1.0.0 , Chapter 1. Boost.LocalFunction 1.0.0
|
Локальная функция |
Повышенный.LocalFunction |
C++11 Функция Lambda (не C++03) |
Местный функтор |
Глобальный функтор (не локальный) |
Boost.Phoenix |
---|---|---|---|---|---|
Может быть определен локально |
Да. |
Да. |
Да. |
Следовательно, это не совсем альтернативная реализация локальных функций, но она приведена здесь только для сравнения. |
Да. |
Может быть определен с использованием синтаксиса С++ |
Да. Плюс возможные ошибки компилятора и отладка сохраняют привычный смысл и формат. |
Да. Плюс возможные ошибки компилятора и отладка сохраняют привычный смысл и формат. |
Да. Плюс возможные ошибки компилятора и отладка сохраняют привычный смысл и формат. |
Да. Плюс возможные ошибки компилятора и отладка сохраняют привычный смысл и формат. |
Нет (используется C++шаблон выражениясинтаксис). |
Можно определить в выражениях |
Нет. Оно может быть определено только в заявлениях. |
Да (плюс локальная функция может быть неназвана). |
Нет. Оно может быть определено только в заявлениях. |
Нет. Оно может быть определено только в заявлениях. |
Да (плюс локальная функция может быть неназвана). |
Может передаваться как параметр шаблона (например, в алгоритмы STL) |
Да. СтандартC++03не позволяет передавать локальные типы в качестве параметров шаблона (см.[N2657]), но эта библиотека реализует «трюк», чтобы обойти это ограничение (см. разделРеализация). |
Да. |
Нет компиляторовC++03(но да, компиляторыC++11и некоторые компиляторы, такие как MSVC 8.0, см.[N2657]). |
Да. |
Да. |
Переменные доступа в объеме |
Да. Имена переменных повторяются в объявлении функции, так что они могут быть связаны значением, постоянным значением, ссылкой и постоянной ссылкой (объект |
Да. Имена переменных повторяются в объявлении функции (плюс есть краткий синтаксис, связывающий все переменные в объеме одновременно), так что они могут быть связаны постоянным значением и ссылкой (объект |
No. Программисты должны вручную программировать фанкторы данных и четко указывать их типы для доступа к переменным в объеме. |
No. Программисты должны вручную программировать фанкторы данных и четко указывать их типы для доступа к переменным в объеме. |
Да. Переменные в объеме доступны как обычно в выражениях (плюс |
Полиморфныйв типе параметра функции |
Нет (локальные функции не могут быть шаблонами функций). |
Нетлямбда C++11не могут быть шаблонами функций. |
Нет (местные классы не могут иметь шаблоны функций членов). |
Да. |
Да. |
C++11 Lambda Функция
Функции лямбда C++11имеют большинство функций этой библиотеки плюс некоторые дополнительные функции (см. также пример в разделеВведение):
CopyConstructible
и для связывания требуется (потенциально дорогостоящая) дополнительная операция копирования. Вместо этого постоянная ссылка поддерживается этой библиотекой.этого
, в то время как эти локальные функции библиотеки могут связывать либо выбранные элементы данных, либо весь объектэтого
(с использованиемэтого_
.&
или=
, в то время как эта локальная функция библиотеки всегда требует связывания переменных, именующих их один за другим.Например, для некопируемых объектов (см. такжеnoncopyable_cxx11_lambda_error.cpp
иnoncopyable_local_function.cpp
):
C++11 Lambda Функция |
Повышенный.LocalFunction |
---|---|
повысить[][][][]][20};f();возврат0;] |
Или для объектов с дорогостоящими операциями копирования (см. такжедорогой_copy_cxx11_lambda.cpp
идорогой_copy_local_function.cpp
):
C++11 Lambda Функция |
Повышенный.LocalFunction |
---|---|
nintinintinti[4 Некоторое время занимает копирование.для[476};f();возврат0;] |
струкцияintintint[6 Некоторое время занимает копирование.дляi=0;<;// Зарегистрируйтесь для 'bind&intmainvoidnx[-1voidBOOST_LOCAL_FUNCTIONconstсвязывает&x// OK: Ни один дорогойне утверждаетi==1// копия, но постоянная.}BOOST_LOCAL_FUNCTION_NAMEf]fвозвращают;] |
Когда требуется постоянная функциональность связывания для лямбда-функцийC++11, лучшей альтернативой может быть связывание дополнительной локальной переменной, объявленной постоянной и инициализированной к исходной переменной (например, см.постоянные блоки, реализованные слямбда-функциямиC++11 вПримерыраздела).
Местный функтор
Следующий пример сравнивает локальные функции с локальными функторами C++ (см. такжеadd_local_functor.cpp
иadd.cpp
):
Местный функтор |
Повышенный.LocalFunction |
---|---|
intvoidintсумма=0,фактор=10;структураlocal_add// К сожалению, код boilerplate для программирования класса.local_addint&_sumint_factor[ Body использует синтаксис C++.сумма+=фактор*Число;}частный:// К сожалению, нельзя связывать так повторяющиеся переменные типы.int&сумма;// Доступ 'сумма' по ссылке.constintфактор;// Сделайте 'фактор' константой.добавьтесумму3[8 К сожалению, не может пройти в качестве параметра шаблона к 'std::for_each'.дляразмер_t=0;2;добавить |
intmainvoid// Некоторый локальный объем.intСумма=0,фактор=10;// Переменные в области связывания.пустотаBOOST_LOCAL_FUNCTIONconstbindfactor,bind&sumintintnum]sum+=факторnum;]]]]BOOST_LOCAL_FUNCTION_NAMEдобавить]добавить1;// Вызовите локальную функцию.intnums={2,3std::for_eachnumsnums+2,добавить;// Передайте это алгоритму.BOOST_TESTсумма==60;// Установить итоговое итоговое значение.возвратповышение::отчет_ошибки[;]] |
Глобальный функтор
Следующий пример сравнивает локальные функции с глобальными функторами C++ (см. такжеadd_global_functor.cpp
иadd.cpp
):
Глобальный функтор |
Повышенный.LocalFunction |
---|---|
// К сожалению, не может быть определено локально (так что не является реальной альтернативой).структурglobal_add// К сожалению, код boilerplate для программирования класса.global_addint&_sumint_factor_ sum_sum_sum_sum_sum[13 Тело использует синтаксис утверждения C++.сумма+=фактор*Число;]частное:// К сожалению, нельзя связывать так повторяющиеся типы переменных.int∑// Доступ «сумма» по ссылке.constintintvoidvoidфакторфактор[1316BOOST_TESTсумма==60;возвратповышение::отчет_ошибки[;]] |
intmainvoid// Некоторый локальный объем.intСумма=0,фактор=10;// Переменные в области связывания.пустотаBOOST_LOCAL_FUNCTIONconstbindfactor,bind&sumintintnum]sum+=факторnum;]]]]BOOST_LOCAL_FUNCTION_NAMEдобавить]добавить1;// Вызовите локальную функцию.intnums={2,3std::for_eachnumsnums+2,добавить;// Передайте это алгоритму.BOOST_TESTсумма==60;// Установить итоговое итоговое значение.возвратповышение::отчет_ошибки[;]] |
Однако обратите внимание, что глобальные функторы не позволяют определить функцию локально, поэтому они не являются реальной альтернативой реализации локальных функций.
Boost.Phoenix
Следующий пример сравнивает локальные функции сBoost.Phoenix(см. такжеadd_phoenix.cpp
иadd.cpp
):
Boost.Phoenix |
Повышенный.LocalFunction |
---|---|
std::for_eachnums,nums+3,Let_f=crefфакторК сожалению, тело не может использовать синтаксис утверждения C++.refsum]+=_f*_1_1// Доступ 'сумма' по ссылке.BOOST_TESTсумма==повышениеотчет_ошибки | intmainvoid// Некоторый локальный объем.intСумма=0,фактор=10;// Переменные в области связывания.пустотаBOOST_LOCAL_FUNCTIONconstbindfactor,bind&sumintintnum]sum+=факторnum;]]]]BOOST_LOCAL_FUNCTION_NAMEдобавить]добавить1;// Вызовите локальную функцию.intnums={2,3std::for_eachnumsnums+2,добавить;// Передайте это алгоритму.BOOST_TESTсумма==60;// Установить итоговое итоговое значение.возвратповышение::отчет_ошибки[;]] |
Сравнение в этом разделе не включает библиотекуBoost.Lambda, потому что эта библиотека устарела и была замененаBoost.Phoenix. Для этого сравнения используется библиотекаBoost.Phoenixверсии 3.0.
Следующие таблицы сравнивают время выполнения, время компиляции и двоичные размеры для различных альтернатив локальным функциям, представленным в этом разделе.
В целом, эта библиотека имеет время компиляции и генерирует двоичные размеры, аналогичные тем, которые используются в других подходах. Это время выполнения библиотеки на компиляторахC++03было измерено как большее, чем другие подходы, когда включена оптимизация компилятора (с использованиемbjamrelease...
). Однако на компиляторах, которые позволяют передавать локальные типы в качестве параметров шаблона (например, MSVC 8.0 или GCC 4.5.3 с включенными функциямиC++11-std=c++0x
, см. также[N2657]иBoost.Config'sBOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
) эта библиотека автоматически генерирует оптимизированный код, который работает так же быстро, как и самый быстрый из других подходов (см. подход «Boost.LocalFunction» ниже). Когда эта локальная функция библиотеки указанаinline
(см. ниже подход «Boost.LocalFunction Inline» иРасширенная тематика (раздел 2133) всегда сопоставима с подходами «Локальный функтор» и «Глобальный функтор». Однако в этих случаях локальная функция не может быть переносима в качестве параметра шаблона (см.[N2657]иBoost.Config'sBOOST_NO_CXX11_LOCAL_CLASS_TEMPLATE_PARAMETERS
), поэтомуstd::for_each
заменяется на for-loop (на MSVC for-loop, а не на локальную функцию фактически то же самое относится к локальным функторам, было измерено, чтобы иметь худшие характеристики, чем использованиеstd::для_each
. Наконец, это время выполнения библиотеки всегда является одним из самых быстрых, когда не включена оптимизация компилятора (используяbjamотладка...
).
![]() |
Note |
---|---|
Производительность времени выполнения этих локальных функций библиотеки объясняется тем, что наC++03совместимых компиляторах (например, GCC 4.5.3 без |
Эта стоимость исполнения на компиляторахC++03может быть или не быть проблемой в зависимости от требований к производительности конкретных приложений. Например, приложение может уже использовать ряд косвенных вызовов функций (функциональные указатели, виртуальные функции и т.д.), для которых накладные расходы, добавленные с помощью одного дополнительного указателя функций, требуемого локальным вызовом функций, могут быть незаметны в течение общего времени выполнения программы.
Наконец, обратите внимание, что для анаилсиса, представленного здесь, использовался только очень простой локальный функциональный орган с только одной инструкцией (см. исходные файлы ниже). Авторы не изучили, как эта библиотека и другие подходы будут работать по отношению друг к другу, когда более сложный набор инструкций запрограммирован для локального функционального тела (например,, еслиболее сложный набор инструкций в локальном функциональном теле должен был ингибировать некоторый компилятор от встраивания функциональных объектов, а также другие подходы, такие какC++11 лямбда-функциииBoost.Phoenixможет начать показывать более высокие сроки выполнения даже при включенной оптимизации).
Следующие команды были выполнены из каталога примеров библиотеки для измерения времени компиляции, двоичного размера и времени выполнения соответственно:
> touch <FILE_NAME>.cpp # force recompilation > python chrono.py bjam {release|debug} <FILE_NAME> # compile-time > size <FILE_NAME> # binary size > ./<FILE_NAME> # run-time
Локальная функция была названа1e8
раз, чтобы сложить все элементы вектора, и время выполнения было измерено с использованиемBoost.Chronoв среднем по10
исполнений суммирования вектора (см. исходные файлы ниже).
Легенда |
Подход |
Источник файла |
---|---|---|
Boost.LocalFunctioninline |
||
Местный функтор |
||
Глобальный функтор |
||
GCC 4.5.3 Функции C++11 Lambda и «Местные классы как параметры шаблона» |
---|
Составлено с |
Составлено с |
MSVC 8.0 «Местные классы как параметры шаблона» (без функций лямбды C++11) |
---|
Составлено с |
Составлено с |
Статья Annex: Alternatives раздела Chapter 1. Boost.LocalFunction 1.0.0 Chapter 1. Boost.LocalFunction 1.0.0 может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: Chapter 1. Boost.LocalFunction 1.0.0 ::
реклама |