C++为了函数的灵活使用,提供了不少的语言特性以及库对函数使用的支持。 首先是语言特性的支持,其中包括函数指针和C++11中引入的lambda表达式,还有标准库对函数使用的支持,其中主要包括函数适配器,以及泛型的function,基本取代了函数指针的使用。
一、函数指针
int love(const string &s)
{
cout<<"I love "<<s<<endl;
}
int hate(const string &s)
{
cout<<"I hate "<<s<<endl;
}
void get_love(decltype(love) *fc,const string &s) ///decltype将函数类型未自动转化为函数指针,而函数参数不能为函数类型,因此需要加指针修饰符
{
fc(s);
}
int (*fis)(const string&);
fis = &love; ///可将love的地址赋给fis
fis("Hello , GNU!");
auto lovep = love; ///lovep 是指向love的指针
get_love(lovep,"GCC");
get_love(hate,"Windows");int love(const string &s)
{
cout<<"string "<<s<<endl;
}
int love(const string &s,unsigned ui)
{
cout<<"int "<<ui<<" \tstring "<<s<<endl;
}
int (*lovepx)(const string&) = love;
int (*lovepy)(const string&,unsigned)=love;
lovepx("Open Source");
lovepy("To C or not to C",2);二、lambda表达式
除了函数指针以外,C++11还引入了lambda表达式,每定义一个lambda表达式,编译器或为其生成一个内部类,同时定义该类的一个对象。
其简单的使用:
vector<string> vs={"one","two","three","four","five","six","seven"};
sort(vs.begin(),vs.end(),[](const string &x,const string &y){
///将字符串按照最后一个字母的大小排序
return *(x.crbegin()) < *(y.crbegin());
});
for_each(vs.cbegin(),vs.cend(),[](const string& s){
///输出到标准输出
cout<<s<<endl;
});
cout<<endl;lambda表达式一般多用于在函数内部传递一些小的操作,这种情况下我们就不必定义一个函数,而直接使用lambda表达式,他的限制是,不能在函数之间共享,同时太复杂的操作也不建议使用lambda表达式。当其返回值不是太复杂,而且只有一个返回语句时,可以省略其返回值声明,由编译器根据return语句自动推导,需要返回值时,可以如下书写
vector<string> vs={"Follow","My","Heart","!","Run","Say"};
transform(vs.cbegin(),vs.cend(),vs.begin(),[](const string &s)->string
{
if(s.size() > 5)
{
return s.substr(0,5);
}
else
{
return s;
}
});
map<unsigned,string> mp={ {0,"zero"},{1,"one"},{2,"two"},
{3,"three"},{4,"four"},{5,"five"} };
int a=3;
///按值共享
for_each(mp.cbegin(),mp.cend(),[a](const pair<unsigned,string> p)
{
if(p.first > a)
{
cout<<p.first<<"\t"<<p.second<<endl;
}
else
{
cout<<p.first<<"\t"<<p.second+"!"<<endl;
}
});
int sum=0;
vector<int> vit = {1,2,3,4,5,6,7,8,9,0};
///按引用共享
for_each(vit.cbegin(),vit.cend(),[&sum](int i)
{
sum += i;
});
///a按值共享,sum按引用共享
for_each(vit.cbegin(),vit.cend(),[a,&sum](int i)
{
if(i > a)
{
sum += i;
}
});
///除了sum之外,所有的局部变量按值共享
for_each(vit.cbegin(),vit.cend(),[=,&sum](int i)
{
if(i < a)
{
sum += i;
}
});
///除了a以外,所有的局部变量都按照引用共享
for_each(vit.cbegin(),vit.cend(),[&,a](int i)
{
if(i != a)
{
sum += i;
}
});三、关于bind
C++11中引入了bind,将原来复杂的参数绑定同一为一个接口,变得简单了
例如:
///将不小于5的元素删除
vector<unsigned> vs={0,1,2,3,4,5,6,7,8,9,10};
unsigned flag=5;
vs.erase(remove_if(vs.begin(),vs.end(),
bind(less_equal<unsigned>(),std::placeholders::_1,flag)),vs.end());
for(const auto &item:vs)
{
cout<<item<<endl;
}
利用这个特性,还可以做更有趣的事情:
///按照降序排序
vector<unsigned> vs={0,1,2,3,4,5,6,7,8,9,10};
sort(vs.begin(),vs.end(),
bind(less_equal<unsigned>(),std::placeholders::_2,std::placeholders::_2));
for(const auto &item:vs)
{
cout<<item<<endl;
}
bind函数还可以用来绑定成员函数
class Boy
{
public:
void love(const string &s)const
{
cout<<"I love "<<s<<endl;
}
};
Boy by;
string dear=" beauty girl";
auto fcx = bind(&Boy::love,by,std::placeholders::_1);
auto fcy = bind(&Boy::love,std::placeholders::_1,dear);
fcx(dear);
fcy(by);注意:bind不能用来绑定重载函数
四、关于function
function是C++11中引入的可对同类函数提供统一接口的适配器
例如:
class Boy
{
public:
int love(const string &s)const
{
cout<<"I love "<<s<<endl;
}
int operator()(const string &s)
{
}
};
int love(const string &s)
{
}
Boy by;
auto lambdaf = [](const string &){return 0;};
auto bindf = bind(&Boy::love,by,std::placeholders::_1);
vector<function<int(const string&)>> vf={lambdaf,bindf,love,by};
vf[0]("Apple");
vf[1]("Google");
vf[2]("Facebook");
vf[3]("IBM");
function<bool(const string&)> fcx = &string::empty; ///通过传递引用来调用
function<bool(const string*)> fcxx = &string::empty; ///通过传递指针来调用
///既可以传递引用也可以传递指针来调用
auto fcy = mem_fn(&string::empty);
auto fcz = bind(&string::empty,std::placeholders::_1);
vector<string> vs = {"American","China","Japan","England","Russia"};
vs.erase(remove_if(vs.begin(),vs.end(),fcy),vs.end());
copy_if(vs.begin(),vs.end(),vs.begin(),fcz);
find_if(vs.begin(),vs.end(),fcx);
原文地址:http://blog.csdn.net/yuanliang01xiaolang/article/details/41343671