Когда Вы используете функциональные объекты в C++?

Я вижу функциональные объекты, используемые часто вместе с алгоритмами STL. Функциональные объекты появились из-за этих алгоритмов? Когда Вы используете функциональный объект в C++? Каковы его преимущества?

11
задан jasonline 28 February 2010 в 15:06
поделиться

6 ответов

Как сказано в jdv, вместо указателей функций используются функторы, которые сложнее оптимизировать и встроить в компилятор; кроме того, фундаментальным преимуществом функторов является то, что они могут легко сохранять состояние между вызовами к ним 1 , поэтому они могут работать по-разному в зависимости от того, когда они вызывались в другой раз, отслеживать как-то параметры, которые у них есть used, ...

Например, если вы хотите просуммировать все элементы в двух контейнерах int, вы можете сделать что-то вроде этого:

struct
{
    int sum;
    void operator()(int element) { sum+=element; }
} functor;
functor.sum=0;
functor = std::for_each(your_first_container.begin(), your_first_container.end(), functor);
functor = std::for_each(your_second_container.begin(), your_second_container.end(), functor);
std::cout<<"The sum of all the elements is: "<<functor.sum<<std::endl;

  1. На самом деле, как указал Р. Самуэль Клатчко ниже, они могут поддерживать несколько независимых состояний , по одному для каждого экземпляра функтора:
    Несколько более точное утверждение состоит в том, что функторы могут поддерживать несколько независимых состояний (функции могут поддерживать одно состояние через статику / глобальные переменные, которые не являются ни поточно-безопасными, ни повторно входимыми).
    Функторы позволяют использовать еще более сложные состояния, например общее состояние (статические поля) и частное состояние (поля экземпляра). Однако эта дополнительная гибкость используется редко.
9
ответ дан 3 December 2019 в 04:13
поделиться

Идея инкапсуляции функции как объекта восходит к Lisp и Smalltalk. Идея функтора C ++ была в главе книги Джима Коплиена Advanced C ++ Programming Styles and Idioms в 1991 году. STL использовал идиому и популяризировал ее.

2
ответ дан 3 December 2019 в 04:13
поделиться

Функциональные объекты были разработаны для обеспечения сильного уровня абстракции над STL, и в этом отношении они великолепны.

Однако я предпочитаю использовать boost :: bind и вместо этого связывать функцию с алгоритмами STL - обычно (, но не в тех случаях, когда объект имеет состояние ), которое кажется более элегантным решением.

std::for_each( callback.begin(), callback.end(), 
    boost::bind(&Callback::call(),_1) 
);

Кроме того, еще одна предстоящая альтернатива - лямбда-выражения в C ++ 0x (пример, беззастенчиво украденный из Википедии):

std::vector<int> someList;
int total = 0;
std::for_each(someList.begin(), someList.end(), [&total](int x) {
  total += x;
});
std::cout << total;

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

2
ответ дан 3 December 2019 в 04:13
поделиться

Я не могу сказать, почему они возникли - возможно, просто потому, что они могли!

Когда вы используете функтор? Учтите, что функтор просто перемещает код, который вы обычно помещаете в цикл, в operator () класса, они не сильно отличаются от простого вызова функции в цикле while ... кроме использования их вы позволяете компилятору встроить код, а также можете передать вместо него предварительно созданный объект, который вы создали с некоторым состоянием. Это последнее обстоятельство делает их очень сильными.

Сравните алгоритм сортировки с вызовом qsort CRT. Они делают то же самое, только по-разному.

1
ответ дан 3 December 2019 в 04:13
поделиться

Функциональный объект - это функция, которая также является объектом, то есть имеет состояние. Обычные функции обычно не имеют состояния. Они могут имитировать наличие состояния, обращаясь к глобальным переменным, но тогда состояние будет общим для всех вызовов.

2
ответ дан 3 December 2019 в 04:13
поделиться

Объекты функций (функторы) обычно используются вместо указателей функций. У указателей функций есть проблема: компилятор обычно передает их как необработанные указатели, что затрудняет последующую инкрустацию кода. Кроме того, им легче передавать параметры.

8
ответ дан 3 December 2019 в 04:13
поделиться
Другие вопросы по тегам:

Похожие вопросы: