仿函数是一种重载了函数调用运算符(operator())的类或结构体,它可以像函数一样被调用。仿函数可以在很多STL算法中使用,例如sort、for_each、transform等,可以自定义排序规则、操作、条件等等。通过仿函数,C++程序员可以更加灵活地实现自己的算法。
与普通函数不同,仿函数可以保存状态,因此在使用仿函数时可以灵活地传递参数并进行计算,非常适用于一些复杂的算法和数据结构的实现。
在C++中,函数指针可以作为参数传递和返回值,但是函数指针只能指向函数,无法指向类成员函数和lambda表达式。而仿函数可以作为一种通用的函数封装,可以指向函数、类成员函数以及lambda表达式,并且可以保存状态。因此,仿函数比函数指针更加灵活和可扩展。
仿函数可以像函数一样被调用
class MyFunctor {
public:
void operator() (int i) {
cout << i << endl;
}
};
MyFunctor myFunctor;
myFunctor(123);
//结果
//123
在STL算法中,仿函数也可以作为函数参数传递
vector<int> vec{3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5};
sort(vec.begin(), vec.end(), greater<int>());
for_each(vec.begin(), vec.end(), MyFunctor());
其中,greater()是一个内置的仿函数对象,用于实现降序排列。
一元仿函数是指只有一个参数的仿函数
template <typename T>
struct MyFunctor1 {
void operator() (T val) {
cout << val << endl;
}
};
template <typename T>
struct MyFunctor2 {
T operator() (T val) {
return val * val;
}
};
二元仿函数是指有两个参数的仿函数
template <typename T>
struct MyFunctor3 {
bool operator() (T val1, T val2) {
return val1 < val2;
}
};
在STL算法中,一元仿函数和二元仿函数通常用于排序、查找、遍历等操作。
函数适配器是一种特殊的仿函数,它用于将一个仿函数适配到另一个仿函数或函数对象上。STL中常用的函数适配器有:bind1st、bind2nd、not1、not2、logical_and、logical_or等
template <typename T>
struct MyFunctor4 {
bool operator() (T val) {
return val > 0;
}
};
vector<int> vec{3, -1, 4, -1, 5, -9, 2, -6, 5, 3, -5};
count_if(vec.begin(), vec.end(), not1(MyFunctor4<int>()));
//结果
//3
其中,not1是一个函数适配器,它将MyFunctor4适配成一个返回相反值的仿函数对象,从而统计出vec中小于等于0的元素个数。
仿函数的实现首先要重载函数调用运算符(operator()),并根据需要定义参数和返回值
template <typename T>
struct MyFunctor1 {
void operator() (T val) {
cout << val << endl;
}
};
template <typename T>
struct MyFunctor2 {
T operator() (T val) {
return val * val;
}
};
其中,MyFunctor1是一个一元仿函数,用于输出参数值,而MyFunctor2是一个一元仿函数,用于计算参数的平方。
仿函数通常是一个模板类,可以支持不同的参数类型
template <typename T>
struct MyFunctor3 {
bool operator() (T val1, T val2) {
return val1 < val2;
}
};
其中,MyFunctor3是一个二元仿函数,用于比较两个参数的大小。
仿函数也可以使用函数适配器来实现。例如,使用bind1st函数适配器将一个二元仿函数适配成一个一元仿函数
template <typename T>
struct MyFunctor4 {
bool operator() (T val1, T val2) {
return val1 < val2;
}
};
MyFunctor4<int> myFunctor;
bind1st(myFunctor, 10)(5);
//结果
//false
其中,bind1st将myFunctor适配成一个只有一个参数的仿函数,第一个参数被绑定为10,然后用5调用这个仿函数,返回false。
class AddFunctor{
public:
AddFunctor(int n):m_n(n){}
int operator()(int x) const{
return x + m_n;
}
private:
int m_n;
}
在上面的代码中,我们定义了一个AddFunctor类,它带有一个整型参数n,表示每次调用要加上的值。在调用运算符()时,返回x加上m_n的结果。
使用AddFunctor类,可以有如下示例
int main()
{
AddFunctor add(3);
int result = add(5); //结果为8
return 0;
}
在STL中,许多算法都需要使用仿函数。例如:
通过使用仿函数,我们可以将算法和数据结构解耦,是的算法更加通用和灵活。
在使用仿函数时需要注意以下几点
在C++11中,可以使用constexpr关键字来声明一个函数或变量是常量表达式,可以在编译时计算。如果一个仿函数的operator()是一个常量表达式,可以使用constexpr来进行优化
template <typename T>
struct MyFunctor1 {
constexpr T operator() (T val) const {
return val * val;
}
};
这样,当使用MyFunctor1时,如果参数是一个常量表达式,那么编译器就可以在编译时计算出结果,从而提高程序的执行效率。
仿函数可以使用inline关键字来声明为内联函数,从而在编译时将函数体直接嵌入到调用处,避免了函数调用的开销
template <typename T>
struct MyFunctor2 {
inline T operator() (T val) const {
return val * val;
}
};
C++11引入了lambda表达式,可以方便地定义一个匿名仿函数。与普通的仿函数相比,使用lambda表达式可以减少代码的冗余,从而提高程序的可读性和维护性
vector<int> vec{3, -1, 4, -1, 5, -9, 2, -6, 5, 3, -5};
auto count = count_if(vec.begin(), vec.end(), [](int val) { return val > 0; });
其中,lambda表达式[] (int val) { return val > 0; }定义了一个匿名仿函数,用于统计vec中大于0的元素个数。
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
如何在Ruby中按名称传递函数?(我使用Ruby才几个小时,所以我还在想办法。)nums=[1,2,3,4]#Thisworks,butismoreverbosethanI'dlikenums.eachdo|i|putsiend#InJS,Icouldjustdosomethinglike:#nums.forEach(console.log)#InF#,itwouldbesomethinglike:#List.iternums(printf"%A")#InRuby,IwishIcoulddosomethinglike:nums.eachputs在Ruby中能不能做到类似的简洁?我可以只
说在前面这部分我本来是合为一篇来写的,因为目的是一样的,都是通过独立按键来控制LED闪灭本质上是起到开关的作用,即调用函数和中断函数。但是写一篇太累了,我还是决定分为两篇写,这篇是调用函数篇。在本篇中你主要看到这些东西!!!1.调用函数的方法(主要讲语法和格式)2.独立按键如何控制LED亮灭3.程序中的一些细节(软件消抖等)1.调用函数的方法思路还是比较清晰地,就是通过按下按键来控制LED闪灭,即每按下一次,LED取反一次。重要的是,把按键与LED联系在一起。我打算用K1来作为开关,看了一下开发板原理图,K1连接的是单片机的P31口,当按下K1时,P31是与GND相连的,也就是说,当我按下去时
我需要一个通过输入字符串进行计算的方法,像这样function="(a/b)*100"a=25b=50function.something>>50有什么方法吗? 最佳答案 您可以使用instance_eval:function="(a/b)*100"a=25.0b=50instance_evalfunction#=>50.0请注意,使用eval本质上是不安全的,尤其是当您使用外部输入时,因为它可能包含注入(inject)的恶意代码。另请注意,a设置为25.0而不是25,因为如果它是整数a/b将导致0(整数)。
我需要从json记录中获取一些值并像下面这样提取curr_json_doc['title']['genre'].map{|s|s['name']}.join(',')但对于某些记录,curr_json_doc['title']['genre']可以为空。所以我想对map和join()使用try函数。我试过如下curr_json_doc['title']['genre'].try(:map,{|s|s['name']}).try(:join,(','))但是没用。 最佳答案 你没有正确传递block。block被传递给参数括号外的方法
在这段Ruby代码中:ModuleMClassC当我尝试运行时出现“'M:Module'的未定义方法'helper'”错误c=M::C.new("world")c.work但直接从另一个类调用M::helper("world")工作正常。类不能调用在定义它们的同一模块中定义的模块函数吗?除了将类移出模块外,还有其他解决方法吗? 最佳答案 为了调用M::helper,你需要将它定义为defself.helper;结束为了进行比较,请查看以下修改后的代码段中的helper和helper2moduleMclassC
也许这听起来很荒谬,但我想知道这对Ruby是否可行?基本上我有一个功能...defadda,bc=a+breturncend我希望能够将“+”或其他运算符(例如“-”)传递给函数,这样它就类似于...defsuma,b,operatorc=aoperatorbreturncend这可能吗? 最佳答案 两种可能性:以方法/算子名作为符号:defsuma,b,operatora.send(operator,b)endsum42,23,:+或者更通用的解决方案:采取一个block:defsuma,byielda,bendsum42,23,
所以我正在研究RubyKoans,而且我遇到了一个我认为是ruby1.9.x特有的问题。deftest_calling_global_methods_without_parenthesesresult=my_global_method2,3assert_equal5,resultend我明白了:james@tristan:~/code/ruby_projects/ruby_koans$rake(in/home/james/code/ruby_projects/ruby_koans)cdkoans/home/james/.rvm/rubies/ruby-1.9.2-p180/bin/ru