函数对象与函数指针

kum*_*ran 10 c++ algorithm stl function-pointers function-object

我有两个与函数对象和函数指针相关的问题,


问题:1

当我读到sortSTL 的不同用途算法时,我看到第三个参数可以是一个函数对象,下面是一个例子

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() );  
Run Code Online (Sandbox Code Playgroud)

题 :

现在,声明怎么样sort(union, union+50,PopLess())PopLess()必须解析成PopLess tempObject.operator()operator ()在临时对象上执行函数相同的东西.我将此视为,将重载操作的返回值bool(如我的示例中)传递给sort算法.

那么,在这种情况下,sort函数如何解析第三个参数?


问题2

我们是否使用函数对象与函数指针相比​​具有任何特定优势?如果我们使用下面的函数指针它会导致任何不利吗?

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

PS:以上参考文献(包括示例)均来自"Stephen C. Dewhurst"的书"C++ Common Knowledge:Essential Intermediate Programming".
我无法解码主题内容,因此已发布求助.

在此先感谢您的帮助.

Jam*_*lis 8

PopLess()实例化PopLess要传递给的类的临时实例std::sort().它实际上就像你说的那样(注意在这个例子中有一个额外的副本):

PopLess pl = PopLess();
sort(union, union + 60, pl);
Run Code Online (Sandbox Code Playgroud)

然后,std::sort()将调用该operator()实例.

至于函数对象或函数指针是否更好"更好",它取决于.可能最重要的区别是函数对象可以维持状态,而指针传递的普通函数则不能.编译器可能能够更好地优化其中一个,但在大多数使用场景中可能并不重要.

  • 通常函数对象导致代码比函数指针更快,因为编译器通常不能通过函数指针内联调用,而函数对象的`operator()()`成员函数可以很容易地内联. (3认同)
  • 我认为,James所指的是 - 在函数指针级别 - 不同的调用没有状态维护范围.因此,如果您正在使用函数指针并且多次调用sort,则不能为每个函数指定不同的状态.这可以通过功能对象来实现.如果我错了,请纠正我. (2认同)

utn*_*tim 5

问题1:

PopLess()必须解析为PopLess > tempObject.operator()与临时对象上执行operator()函数相同的内容.

它不像你说的那样扩展.PopLess()实际上是对隐式PopLess::PopLess()构造函数的调用.此代码创建一个临时对象,并将其传递给函数调用中的第3个参数.

问题2

我们是否使用函数对象与函数指针相比​​具有任何特定优势?

不是在这种情况下.这里你的PopLess对象是无状态的.您可以创建具有内部状态的仿函数(函数对象).

例:

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));
Run Code Online (Sandbox Code Playgroud)

此代码将输出序列中的所有数字,确保输出中的所有数字都具有最小值1(输出为1 - 如果原始数字少于 - 或原始数字,如果原始数字大于或等于1).