C++谓词、lambda与bind

谓词、lambda与bind

    • 定制操作
    • lambda表达式
    • 参数绑定

定制操作

  • 学习STL标准库过程中,了解到许多算法都会比较序列中的元素,甚至有些容器自带都会比较元素的顺序(如SET)
  • 一般而言,这类算法使用元素类型的重载运算符(operate <==)来完成元素之间的比较。
  • 为了方便我们根据实际需求来完成排序,STL允许我们提供自己定义的操作来代替默认运算符
    举个栗子,比方说我们有一个string类型的vector容器,其中含有以下几个单词

“foxes”,“yellow”,“theme” ,“odd”, “slow”

现在,要求按照单词的长短进行排序,且要求从长到短进行排列。解决这个问题,可以用到sort函数进行排序,但是,问题在于如何满足从长到短这个条件,于是我们可以,定义一个可调用的表达式,称为谓词(predicate)进行重载sort函数

  • 话不多说,我们来定义这个谓词,上代码
bool check_size(const string &a, const string &b)
{
	return (a.size () >= b.size ());
}

很直观,这个谓词就是返回一个布尔值,且接收两个string类型参数,所以也称为二元谓词(binary predicate),当然相对应的,也就有一元谓词(unary predicate)。那怎么使用呢?看下面:

// 定义一个vector存储上面的单词
vector<string> words = { "foxes","yellow","theme" ,"odd", "slow" };

// 调用sort算法,将谓词check_size作为参数传入
stable_sort (words.begin (), words.end (), check_size);

// 打印结果
for  (string &s : words)
{
	// 打印重排列后的元素
	cout << s << " ";
}

输出

yellow theme foxes slow odd

细心的读者发现,这个谓词有点类似于函数指针,都能够作为参数传入另一个函数。但两者又有本质不同,只是形式上有相似性。

lambda表达式

众所皆知,C++11标准引入了lambda表达式,其实质就是一个匿名函数。我们可以方便的用其替代上述谓词。其基本的语法如下:

[捕获列表] (参数列表) {函数体}

  • 与普通函数不同,lambda函数没有函数名,取而代之的是捕获列表,能够获取表达式所在函数体的参数,且除了不需指定返回类型外,其他部分与一般函数相同
    那么,我们再来实践一下:
// 将上面的函数替换如下lamda表达式
stable_sort(words.begin(), words.end(), 
	[](const string &a, const string &b)
		{return a.size() >= b.size(); });

可以输出与上面相同的结果,好处就是不用额外定义一个函数啦~

参数绑定

与lambda表达式相对应,标准库提供了一个bind函数供我们个性化使用。其根本设置意图在于适配,因为有的函数要求接受一个一元谓词,而我们定义的函数是二元谓词,但是我们又不想改变这个函数。那么STL给出了解决方案—bind函数

  • 假设定义的函数还是:
bool check_size(const string &a, const string &b)
{
	return (a.size () >= b.size ());
}

我们要使用的算法是find_if,即找到一个长度大于等于int sz = 5的元素,若用lambda表达式,很容易写出

int sz = 5;
vector<string>::iterator i =  find_if(words.begin() , words.end(), 
	[sz](const string &a)
		{return a.size() >= sz; });

cout << *i << endl;

输出

yellow

  • 但是,如果我们坚持要用定义的check_size函数怎么办呢?举个栗子
// 用字符串长度为5代替
string sz = "abcde";

// bind绑定占位符_1到check_size第一个形参 
auto compare = bind(check_size, _1, sz);
vector<string>::iterator i = find_if(words.begin(), words.end(), compare);

cout << *i << endl;

输出

yellow

  • 结果完全相同有木有,需要注意的是,这里的compare是一个函数对象,可以直接传入find_if函数的形参中。
  • 那我们如何直接使用它呢?
string s = "hello";
bool b1 = compare(s);

cout << b1 << endl;

输出

1

其实,bind的作用也很多,例如可以改变形参顺序,或者加入ref()函数可以进行引用绑定(默认值拷贝方式传递)。

你可能感兴趣的:(c++)