C++ Function Pointer, Function Object and C++11 function Object

Keywords: Lambda

1. Definition:

Function object: All class objects that overload the function call operator (operator()) are also called function sub-objects. In STL, function pointers (ps: set and multiset must be function objects, not function pointers) can be used in most places where function subunits are used. By setting operator to inline functions, program performance can be accelerated.

Function pointer: A pointer to a function type (function parameter, return value). Each function has an entry address, which is the entry address of the function. By passing function pointers into functions, it is convenient for one function to call another type of function. For example: int GetMaxValue (double x, bool (*ptr)(int, int), where PTR is the function pointer.  

Function pointers are used in c++:

bool greaterNum(int x, int y)
{
    return x>y;
}                 
using PF = bool (*)(int, int);  //Or typedef int (*PF)(int, int);
PF pf = greaterNum;
cout<<pf(4,10)<<endl; //Output is 0

2. Examples:

Using function pointer and function object as parameters of sort in STL, real # include < iostream >

#include <vector>
#include <algorithm>
#include <functional>

using namespace std;

template<typename T>
class GreaterNum : public binary_function<T, T, bool>
{
public:
    inline bool operator()(T x, T y)
    {
        return x>y;
    }
};

bool greaterNum(int x, int y)
{
    return x>y;
}

void print(int x)
{
    cout<<x<<" ";
}

int main()
{
    vector<int> v1 = {21,6,21,4,2,1,45,6,1,7,9,5,2};
    auto v2 = v1;
    /*Use the function object as the third parameter*/
    sort( v1.begin(), v1.end(), GreaterNum<int>() );
    for_each(v1.begin(), v1.end(), print);
    cout<<endl;
    /*Use the function pointer as the third parameter*/
    sort( v2.begin(), v2.end(), greaterNum );
    for_each(v2.begin(), v2.end(), print);
    
    return 0;
}
3. Advantages of function objects:

(1) Function object is realized by overloading (), then setting operator() function as inline function can improve the running speed of the program. As shown in the example above, the program runs faster when the input greaterNum < int > function is a greaterNum < int > function than when the input greaterNum function pointer is the third parameter of sort. Because inline functions expand at compile time and function pointers are called.

(2) Function objects can carry additional information, such as other data members of the class, while function pointers cannot.

 

4.C++11 function object

Introduction: Stencil-like std::function is a versatile and polymorphic function encapsulation. std::function can encapsulate any entity that can be invoked, including ordinary functions, Lambda expressions, function pointers, and other function objects. std::function object is a type-safe package for existing callable entities in C++ (we know that callable entities such as function pointers are type-insecure).  
Normally std::function is a function object class, which wraps any other function object. The wrapped function object has type T1,... N parameters of TN and returns a value that can be converted to type R. std::function uses a template transformation constructor to receive wrapped function objects; in particular, closure types can be implicitly converted to std::function.  
That is to say, by encapsulating various callable entities (ordinary functions, Lambda expressions, function pointers, and other function objects) in C++ with std::function, a new callable std::function object is formed; let's not entangle so many callable entities any more. Everything becomes simple and rough.

#include <functional>
#include <iostream>
using namespace std;
 
std::function< int(int)> Functional;
 
// Ordinary function
int TestFunc(int a)
{
    return a;
}
 
// Lambda expression
auto lambda = [](int a)->int{ return a; };
 
// Functor
class Functor
{
public:
    int operator()(int a)
    {
        return a;
    }
};
 
// 1. Class member functions
// 2. Class static functions
class TestClass
{
public:
    int ClassMember(int a) { return a; }
    static int StaticMember(int a) { return a; }
};
 
int main()
{
    // Ordinary function
    Functional = TestFunc;
    int result = Functional(10);
    cout << "Ordinary function:"<< result << endl;
 
    // Lambda expression
    Functional = lambda;
    result = Functional(20);
    cout << "Lambda Expression:"<< result << endl;
 
    // functor
    Functor testFunctor;
    Functional = testFunctor;
    result = Functional(30);
    cout << "Similar functions:"<< result << endl;
 
    // Class membership function
    TestClass testObj;
    Functional = std::bind(&TestClass::ClassMember, testObj, std::placeholders::_1);
    result = Functional(40);
    cout << "Class member functions:"<< result << endl;
 
    // Class static function
    Functional = TestClass::StaticMember;
    result = Functional(50);
    cout << "Class static functions:"<< result << endl;
 
    return 0;
}

 

Posted by jspodisus on Wed, 24 Jul 2019 19:31:56 -0700