Когда вы используете объекты функций в С++?
Я вижу функциональные объекты, которые часто используются вместе с алгоритмами STL. Из-за этих алгоритмов возникли функциональные объекты? Когда вы используете объект функции в С++? В чем его преимущества?
Ответы
Ответ 1
Как сказано jdv, вместо указателей функций используются функторы, которые сложнее оптимизировать и встроить в компилятор; кроме того, фундаментальным преимуществом функторов является то, что они могут легко сохранять состояние между вызовами к ним 1 поэтому они могут работать по-разному в зависимости от других случаев, когда они были вызваны, отслеживать каким-либо образом параметров, которые они использовали,...
Например, если вы хотите суммировать все элементы в двух контейнерах ints, вы можете сделать что-то вроде этого:
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;
- На самом деле, как показал R Samuel Klatchko, они могут поддерживать несколько независимых состояний, по одному для каждого экземпляра-функтора:
Несколько более точное утверждение состоит в том, что функторы могут поддерживать несколько независимых состояний (функции могут поддерживать одно состояние через statics/globals, который не является ни потокобезопасным, ни реентерабельным).
Функторы позволяют использовать еще более сложные состояния, например, общее состояние (статические поля) и личное состояние (поля экземпляра). Однако эта дополнительная гибкость редко используется.
Ответ 2
Функциональные объекты (функторы) обычно используются вместо указателей на функции. У указателей функций есть проблема, что компилятор обычно передает их как необработанные указатели, что затрудняет компилятору встроить код позже. И им легче дать параметры.
Ответ 3
Объекты функций были разработаны таким образом, чтобы обеспечить сильный уровень абстракции над STL, и в этом отношении они великолепны.
Однако я предпочитаю использовать boost::bind
и вместо этого привязывать функцию к алгоритмам STL - обычно (, хотя не в тех случаях, когда объект имеет состояние), что кажется более элегантным решением.
std::for_each( callback.begin(), callback.end(),
boost::bind(&Callback::call(),_1)
);
Кроме того, другой предстоящей альтернативой является lambda в С++ 0x (пример, бесстыдно украденный из Википедии):
std::vector<int> someList;
int total = 0;
std::for_each(someList.begin(), someList.end(), [&total](int x) {
total += x;
});
std::cout << total;
Обратите внимание, что из-за закрытия они не имеют имеют ограничение привязки относительно отсутствия состояния.
Ответ 4
Функциональный объект - это функция, которая также является объектом, то есть имеет состояние. Обычно нормальные функции не имеют состояния. Они могут эмулировать наличие состояния путем доступа к глобальным переменным, но затем состояние делится между всеми вызовами.
Ответ 5
Идея инкапсуляции функции как объекта восходит к Lisp и Smalltalk. Идея функтора С++ была главой книги Джима Коплиена Расширенные стили и идиомы программирования на C++ в 1991 году STL использовал идиому и популяризировал ее.
Ответ 6
Я не могу сказать, почему они появились - возможно, просто потому, что они могли!
Когда вы используете функтор? Учтите, что функтор просто перемещает код, который вы обычно помещаете в цикл в operator() класса, они не сильно отличаются от просто вызова функции в цикле while... кроме того, используя их вы разрешаете компилятору встроить код, и вы также можете передать предварительно сконструированный объект, который вы создали с некоторым состоянием. Этот последний момент делает их очень мощными.
Сравните алгоритм сортировки с вызовом qsort CRT. Они делают то же самое, делайте это совсем по-другому.
Ответ 7
В этой статье мы подробно рассмотрим объекты функций и как сделать код намного более мощным и более чистым.