开发者

function objects versus function pointers

I have two questions related to function objects and function pointers,


Question : 1

When I read the different uses sort algorithm of STL, I see that the third parameter can be a function objects, below is an example

class State {  
  public:  
    //...
    int population() const;  
    float aveTempF() const;  
    //...  
};    
struct PopLess : public std::binary_function<State,State,bool> {  
    bool operator ()( const State &a, const State &b ) const  
        { return popLess( a, b ); }  
};  
sort( union, union+50, PopLess() );  

Question :

Now, How does the statement, sort(union, union+50,PopLess()) work? PopLess() must be resolved into something like PopLess tempObject.operator() which would be same as executing the operator () function on a temporary object. I see this as, passing the return value of overloaded operation i.e bool (as in my example) to sort algorithm.

So then, How does sort function resolve the third parameter in this case?


Question : 2

Question

Do we derive any particular advantage of using function objects versus function pointer? If 开发者_如何学编程we use below function pointer will it derive any disavantage?

inline bool popLess( const State &a, const State &b )
    { return a.population() < b.population(); }  
std::sort( union, union+50, popLess ); // sort by population

PS : Both the above references(including example) are from book "C++ Common Knowledge: Essential Intermediate Programming" by "Stephen C. Dewhurst".

I was unable to decode the topic content, thus have posted for help.

Thanks in advance for your help.


PopLess() instantiates a temporary instance of the class PopLess to be passed to std::sort(). It's effectively the same as if you were to say (note that in this example an extra copy is made):

PopLess pl = PopLess();
sort(union, union + 60, pl);

Then, std::sort() will call the operator() on that instance.

As for whether function objects or function pointers are better "better," it depends. Probably the most important difference is that function objects can maintain state while ordinary functions passed by pointer cannot. A compiler might be able to optimize one or the other better, but in most usage scenarios that's probably not important.


Question 1:

PopLess() must be resolved into something like PopLess > tempObject.operator() which would be same as executing the operator () function on a temporary object.

It's not [expanded as you said]. PopLess() is actually the call to the implicit PopLess::PopLess() constructor. This code creates a temporary object and passes it to the 3rd parameter in the function call.

Question : 2

Do we derive any particular advantage of using function objects versus function pointer?

Not in this case. Here your PopLess object is stateless. You can create functors (function objects) that have internal state.

Example:

struct ensure_min
{
    int value;
    ensure_min(int val) : value(val) {}
    int operator()(const int& i)
    {
        return std::max(value, i);
    }
}

std::vector<int>  values;
values.push_back(-1);
values.push_back(0);
values.push_back(1);
values.push_back(2);
values.push_back(3);

std::transform(values.begin(), values.end(), 
    std::ostream_iterator<int>(std::cout, "\n"), ensure_min(1));

This code will output all the numbers in the sequence, ensuring all the numbers in the output have a minimal value of 1 (the output is either 1 - if the original number was any less - or the original number if the original number was greater than or equal to 1).


Q1: PopLess() constructs an object of type PopLess and sort then uses this object to sort the elements in the range using the operator ().

Looking at the for_each function might be easier, it could be implemented like this:

template <typename IterT, typename Function>
Function for_each( IterT first, IterT last, Function f ) {
    for( ; first != last; ++first )
        f(*first);

    return f;
}

So basically for_each and sort, and functions using function objects, simply take an instance of your function object and call its operator ().

Q2: A compiler might be able to optimize away the function call by inlining when you are using a function object rather than a function pointer, this might not be as straight forward for the compiler to do with the function pointer. Also, a function object can have state.


I'm not sure what Question 1 is asking, but PopLess() is an object. Inside the sort function, this object has its operator() method called to compare the items.


  • Question 1: PopLess() is a temporary object.
  • Question 2: it allows your "function" to have state... you can initialize the object with whatever you like before it gets used as a function


The main practical difference is the ability for a functor to maintain state. For example, sorting multi-column data the functor can have info on which column to sort by, the sort direction and even collation rules (case sensitivity etc.).

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜