Preface
In C++, functors (Functors) refer to overloadingoperator()
Objects of classes or structures, which behave like ordinary functions, can be called like functions. Fiction functions are widely used in STL algorithms, callback mechanisms, function adapters and other scenarios. This article will explore in-depth the concept, advantages and usage of functors, and analyze them in detail based on specific examples.
1. Why do I need a mimicking function?
In C++, we can use normal functions orstd::function
(Introduced in C++11) to define callable objects, but functors have the following advantages in comparison:
- State storage: Normal functions cannot store state, while functors can maintain states inside objects, such as counters, thresholds, etc.
- Performance optimization: Since functors are instances of classes, inline optimization can reduce the overhead of function calls.
- Compatible with STL: STL containers and algorithms use functors widely, such as
std::sort()
Fiction functions are acceptable as custom sorting rules.
2. Basic usage of functors
To define a functor, you need to overload it in a class or structureoperator()
, the examples are as follows:
#include <iostream> // Define functor classesstruct Add { int operator()(int a, int b) { return a + b; } }; int main() { Add add; // Create functor object std::cout << "3 + 5 = " << add(3, 5) << std::endl; // Call like a function return 0; }
Analysis
-
operator()
makeAdd
Objectadd
Become a callable object, similar to a normal functionadd(3, 5)
。 -
operator()
The parameters can be accepted and the calculation results can be returned.
3. Simulation functions with states
A functor can store state so that it holds data between multiple calls. For example, create a functor that calculates the number of calls:
#include <iostream> class Counter { private: int count; public: Counter() : count(0) {} // Initialize counter to 0 int operator()(int value) { count++; return count * value; // Use count to affect the calculation results } int getCount() const { return count; } }; int main() { Counter counter; std::cout << counter(10) << std::endl; // The first call std::cout << counter(10) << std::endl; // The second call std::cout << "Number of calls:" << () << std::endl; return 0; }
Analysis
-
count
Store state as member variable, each calloperator()
Will increasecount
。 - This is very useful in scenarios such as STL algorithms, callback mechanisms, etc.
4. Simulation functions in STL algorithm
STL algorithms usually require comparison, transformation, filtering and other rules, and custom functors are particularly useful at this time. For example, custom sorting:
#include <iostream> #include <vector> #include <algorithm> // Custom comparison rules (descending order)struct Compare { bool operator()(int a, int b) { return a > b; // Sort in descending order } }; int main() { std::vector<int> vec = {5, 2, 8, 1, 3}; std::sort((), (), Compare()); // Pass functor object for (int num : vec) { std::cout << num << " "; } return 0; }
Analysis
-
std::sort()
The default is ascending order, we customize itCompare
As a descending order comparison rule. -
std::sort((), (), Compare());
PassedCompare
Temporary objects of type are used as sorting criteria.
5. Standard imitation functions provided by STL
C++ STL provides some standard functors, mainly in<functional>
In the header file, for example:
- Arithmetic operation functor:
std::plus<T>
、std::minus<T>
、std::multiplies<T>
、std::divides<T>
wait. - Relational operation functor:
std::greater<T>
、std::less<T>
、std::equal_to<T>
wait. - Logical operation functor:
std::logical_and<T>
、std::logical_or<T>
wait.
Example: Usestd::greater<>
Sort in descending order:
#include <iostream> #include <vector> #include <algorithm> #include <functional> // Includes standard imitation functionsint main() { std::vector<int> vec = {5, 2, 8, 1, 3}; std::sort((), (), std::greater<int>()); // Sort by descending order using standard functors for (int num : vec) { std::cout << num << " "; } return 0; }
Analysis
std::greater<int>()
Asstd::sort
Comparison function with what we wrote ourselvesCompare
Similar effects.
6. Lambda replaces functors (C++11)
C++11 introduces Lambda expressions to make the code more concise. Lambda can be used instead of many functor usage scenarios. For example:
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {5, 2, 8, 1, 3}; // Sort in descending order using Lambda std::sort((), (), [](int a, int b) { return a > b; }); for (int num : vec) { std::cout << num << " "; } return 0; }
Why use Lambda?
- Reduce code volume: no need to define separately
struct
As a functor class. - Improve readability: Lambda directly
std::sort()
Define logic at the location, and the code is more intuitive.
Although Lambda is more concise, functors are still a good choice when they need to store state, reuse code, and use across multiple places.
7. Summary
characteristic | Normal functions | Lambda | Simulation functions |
---|---|---|---|
Whether the state can be stored | ❌ No | ⚠️ Closure only | ✅ Yes |
Is it reusable | ✅ Yes | ❌ No (local scope only) | ✅ Yes |
Performance optimization | ⚠️ It may not be possible to inline | ✅ Inline Optimization | ✅ Inline Optimization |
Applicable scenarios | General calculation | Simple one-time logic | STL, callback, complex logic |
When to choose a mimetic function
- Requires storage status (such as a counter).
- Reuse is required (multiple places use the same logic).
- Requires STL compatibility (e.g.
std::sort()
)。 - Efficient optimization (inline) is required.
Fiction functions are an important concept in the C++ language. They enable objects to be called like functions and play an important role in STL algorithms, callbacks, state storage and other scenarios. Although Lambda introduced in C++11 makes the code more concise, functors are still irreplaceable in certain specific scenarios such as STL and state hold.
The above is the concept advantages and detailed content of C++ functors. For more information about C++ functors, please pay attention to my other related articles!