[C ++]-function object

1. The concept of function objects

When it comes to the concept of function objects, everyone may be relatively unfamiliar. First, let's start with the function pointers in the familiar C language.
We also implement the sum function, one is implemented with a function pointer in C language, and the other is implemented with an object in C ++, as shown in the following figure:
Insert picture description here
to see what is different, the C language implementation on the left is the function The address, and the following C ++ way is passed in the sum object, whose object realizes the function by calling the operator function.
From this, you can give a concrete concept of the function object.
Objects with operator () parenthesis operator overload function are called function objects or functors

Second, the benefits of function objects

(1) Achieve compare version one:

template<typename T>
bool compare(T a, T b)
{
	return a > b;
}
int main()
{
	cout << compare(10, 20) << endl;
	cout << compare('b', 'y') << endl;
	return 0;
}

Looking closely at the implementation of the above function, we can think about it, what if we want to implement less than? We ca n’t make frequent changes to the functions in the library, so it leads to the solution of c language function pointers

(2) Use c function pointer solution

template<typename T>
bool mygreater(T a, T b)
{
	return a > b;
}
template<typename T>
bool myless(T a, T b)
{
	return a < b;
}

template<typename T,typename Compare>
bool compare(T a, T b, Compare comp)
{
	return comp(a, b);
}
int main()
{
cout << compare(10, 20, mygreater<int>) << endl;
	cout << compare(10, 20, myless<int>) << endl;
	return 0;
}

The running result is as follows:
Insert picture description here
carefully observe the realization of the above function , there is no way to inline the function call through the function pointer, the efficiency is very low, because of the function call overhead.
Although it is not possible to write the function to be called as an inline function, because the function pointer is called at runtime, but the inline function must be expanded at compile time.
From this, we have derived a solution of the function object

(3) C ++ function object version implementation

template<typename T>
class mygreater
{
public:
	bool operator()(T a, T b)
	{
		return a > b;
	}
};
template<typename T>
class myless
{
public:
	bool operator()(T a, T b)
	{
		return a < b;
	}
};
int main()
{
//此时传入的是两个对象而不是函数的地址
	cout << compare(10, 20, mygreater<int>()) << endl;
	cout << compare(10, 20, myless<int>()) << endl;
	return 0;
}

Benefits function object:
1 call by the function object operator (), you can call overhead omitted function
which function which object is very clear call of the compilation process, thus making use function object is completely inline , province Removed function call overhead

2. Because the function object is generated by a class, you can add related member variables to record more information when the function object is used.
For example, if you want to record how many times this object has been called, you can define a count member variable count in the private member

Third, the application of function objects

Application 1: Priority queue

In the priority queue, the default is the large root heap, but we can change the underlying comparison method to achieve the small root heap, the code is as follows:

int main()
{
	priority_queue<int> que1;//默认的是大根堆
	for (int i = 0; i < 10; i++)
	{
		que1.push(rand() % 100);
	}
	while (!que1.empty())
	{
		cout << que1.top() << " ";
		que1.pop();
	}
	cout << endl;

	//小根堆 改变底层比较的方式
	using MinHeap = priority_queue<int, vector<int>, greater<int>>;
	MinHeap que2;
	for (int i = 0; i < 10; i++)
	{
		que2.push(rand() % 100);
	}
	while (!que2.empty())
	{
		cout << que2.top() << " ";
		que2.pop();
	}
	cout << endl;
	return 0;
}

Application two: set
is the system default in set is less, let's implement the arrangement from large to small

int main()
{
	set<int,greater<int>> set1;
	for (int i = 0; i < 10; i++)
	{
		set1.insert(rand() % 100);
	}
	for (int v : set1)
	{
		cout << v << " ";
	}
	cout << endl;
	return 0;
}
Published 98 original articles · won praise 9 · views 3657

Guess you like

Origin blog.csdn.net/qq_43412060/article/details/105298230