我使用以下示例来说明我的问题:
#include <boost/graph/adjacency_list.hpp>
#include <iostream>
#include <algorithm>
class TestOperator
{
public:
TestOperator(float k):k_(k){};
~TestOperator() {};
float operator() (float m, float s)
{
return (1-k_)*m+k_*m*0.0078*s;
}
private:
float k_;
};
template<typename Operator>
void perform(Operator fun)
{
int value;
value = fun(3.1f,2.5f);
}
template<typename Operator>
void perform2(Operator &fun)
{
int value;
value = fun(3.1f,2.5f);
}
int main()
{
TestOperator myOperator(0.1f);
perform(myOperator);
perform2(myOperator);
return 0;
}
在perform
中,我们在perform2
中使用函数对象作为函数参数wile,我们使用函数对象引用作为函数参数。在关于函数对象的教程中,前一种用法与本教程function objects一样占主导地位。那我的问题是:为什么不使用函数对象引用?对我来说,它更好。有任何想法吗?
答案 0 :(得分:1)
我的指南:
在大多数情况下使用Operator fun
。
仅当Operator& fun
包含不应从fun
的一次调用复制到下一次调用的数据时,才使用operaor()
。例如。如果使用Operator
收集它在容器中保存的数据,则需要通过引用传递fun
。
答案 1 :(得分:1)
在结构中传递成员的函数对象(或仿函数)在按值传递时将被复制,而在通过引用传递时不会被复制。
在您的示例中,成员k_将通过引用调用“生存”,如perform2中所示。如果出于某种原因,在仿函数中保留了信息并且没有初始化,则可能会产生奇怪的副作用。
可以使用pass by reference来收集和保留仿函数中从一次使用到下一次使用的信息。
如果按值传递,则使用的副本将在返回时蒸发,并且调用之间的信息将丢失。
换句话说,原始的仿函数myOperator在执行时没有改变,但它被perform2改变了。
你可以提供一个const myOperator来执行,但不能像声明那样执行2。如果你声明perform2是一个const&amp;,它就不会编译,因为函子中的函数不是const(不能保证不改变仿函数中的东西)。
哪个'更好'还不得而知。在某些情况下,一种比另一种更适用,如果理论上较慢,则副本“更安全”并且更广泛适用。