C++:lambda/函数对象/函数指针(函数名)

STL算法中通常会传入一个谓词来实现自定义的排序,查找数值等行为。
lambda/函数对象/函数指针(函数名)均可以在这个情境中传递信息。在这种情境下对比一下三者的使用:
1.传入函数指针(函数名)
例如,count_if ()函数的第三个参数是一个一元谓词。
若判数一个数能否被3整除,则定义函数:
bool f3(int x) { return x%3==0;}
使用:
int count3 = std::count_if(v.begin(),v.end(),f3);
2.使用函数对象
class f_mod
{
private:
int dv;
public:
f_mod(int d = 1):dv(d){}
bool operator() (int x) {return x%dv == 0;}
};
//也可用struct定义,默认访问属性为public

//定义对象: f_mod mod(3);
count3 = std::count_if(v.begin(),v.end(),f_mod(3));

3.lambda
count3 = std::count_if(v.begin(),v.end(),[] (int x) {return x%3 == 0;});

使用函数需要在本函数外部单独定义一个函数然后用来使用。
函数对象和lambda可以定义在函数内部。 所以代码的修改及可读性更好些。

lambda表达式拓展说明:
(1)lambda表达式完全由一条返回语句组成时,自动类型推断才管用,否则,需要使用返回类型后置语法:
[] (double x) -> double{int y =x ; return x-y ;}
(2)可以给lambda表达式指定一个名称并多次使用
auto mod3 = [] (int x) {return x%3 == 0;}
count1 = std::count_if(v.begin(),v.end(),mod3);
count2 = std::count_if(v.gegin(),v.end(),mod3);
或者像常规函数一样使用有名称的lambda表达式:bool result = mod3(z);
(3)访问变量
[x]按值访问变量x
[=]按值访问所有动态变量
[&]按引用访问所有动态变量
[=,&ed]按引用访问ed,按值访问其它
[&,ted]按值访问ted,按引用访问其它
[ted,&ed]按值访问ted,及按引用访问ed

例:
int count3 = 0;
int count13 = 0;
std::foreach(v.begin(),v.end(),[&] (int x) {count 3+= x%3 ==0; count13 += x%13 ==0;});

其它应用场景,QT中的槽函数可以用lambda表达式
connect(ui->actionquit,&QAction::triggered,={
this->close();
});

函数对象拓展:
//函数模板 重载 函数调用操作符
template
class ShowElemt
{
public:
ShowElemt()
{
n = 0;
}
void operator()(T &t)
{
n++;
cout << t << " ";
}
void printCount()
{
cout << n << endl;
}
public:
int n;
};

//1 函数对象 基本使用
void main11()
{
int a = 100;
FuncShowElemt(a); //普通的函数调用

ShowElemt showElemt; //函数对象
showElemt(a); //函数对象调用
}

template
class Isdiv
{
public:
Isdiv(const T &divisor) //
{
this->divisor = divisor;
}
bool operator()(T &t)
{
return (t%divisor == 0);
}
protected:
private:
T divisor;
};
int a = 4;
Isdiv mydiv(a);

it = find_if(v2.begin(), v2.end(), Isdiv(4));

template
struct SumAdd
{
T operator()(T &t1, T &t2)
{
return t1 + t2;
}
};

vector::iterator it = transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd());

预定义函数对象和函数适配器
1)预定义函数对象基本概念:标准模板库STL提前定义了很多预定义函数对象,#include 必须包含。
//1使用预定义函数对象:
//类模板plus<> 的实现了: 不同类型的数据进行加法运算
void main41()
{
plus intAdd;
int x = 10;
int y = 20;
int z = intAdd(x, y); //等价于 x + y
cout << z << endl;

plus stringAdd;
string myc = stringAdd(“aaa”, “bbb”);
cout << myc << endl;

2)算术函数对象
预定义的函数对象支持加、减、乘、除、求余和取反。调用的操作符是与type相关联的实例
加法:plus
plus stringAdd;
sres = stringAdd(sva1,sva2);
减法:minus
乘法:multiplies
除法divides
求余:modulus
取反:negate
negate intNegate;
ires = intNegate(ires);
Ires= UnaryFunc(negate(),Ival1);

3)关系函数对象
等于equal_to
equal_to stringEqual;
sres = stringEqual(sval1,sval2);
不等于not_equal_to
大于 greater
大于等于greater_equal
小于 less
小于等于less_equal

4)逻辑函数对象
逻辑与 logical_and
logical_and indAnd;
ires = intAnd(ival1,ival2);
dres=BinaryFunc( logical_and(),dval1,dval2);
逻辑或logical_or
逻辑非logical_not
logical_not IntNot;
Ires = IntNot(ival1);
Dres=UnaryFunc( logical_not,dval1);
10.3.2.7函数适配器
1)函数适配器的理论知识

在这里插入图片描述
在这里插入图片描述

2)常用函数函数适配器
标准库提供一组函数适配器,用来特殊化或者扩展一元和二元函数对象。常用适配器是:
1绑定器(binder): binder通过把二元函数对象的一个实参绑定到一个特殊的值上,将其转换成一元函数对象。C++标准库提供两种预定义的binder适配器:bind1st和bind2nd,前者把值绑定到二元函数对象的第一个实参上,后者绑定在第二个实参上。
2取反器(negator) : negator是一个将函数对象的值翻转的函数适配器。标准库提供两个预定义的ngeator适配器:not1翻转一元预定义函数对象的真值,而not2翻转二元谓词函数的真值。
常用函数适配器列表如下:
bind1st(op, value)
bind2nd(op, value)
not1(op)
not2(op)
mem_fun_ref(op)
mem_fun(op)
ptr_fun(op)
3)常用函数适配器案例
//
class IsGreat
{
public:
IsGreat(int i)
{
m_num = i;
}
bool operator()(int &num)
{
if (num > m_num)
{
return true;
}
return false;
}
protected:
private:
int m_num;
};

void main43()
{
vector v1;
for (int i=0; i<5; i++)
{
v1.push_back(i+1);
}

for (vector::iterator it = v1.begin(); it!=v1.end(); it ++)
{
cout << *it << " " ;
}

int num1 = count(v1.begin(), v1.end(), 3);
cout << “num1:” << num1 << endl;

//通过谓词求大于2的个数
int num2 = count_if(v1.begin(), v1.end(), IsGreat(2));
cout << “num2:” << num2 << endl;

//通过预定义函数对象求大于2的个数 greater() 有2个参数
// param > 2
int num3 = count_if(v1.begin(), v1.end(), bind2nd(greater(), 2 ) );
cout << “num3:” << num3 << endl;

//取模 能被2整除的数 求奇数
int num4 = count_if(v1.begin(), v1.end(), bind2nd(modulus (), 2 ) );
cout << “奇数num4:” << num4 << endl;

int num5 = count_if(v1.begin(), v1.end(), not1( bind2nd(modulus (), 2 ) ) );
cout << “偶数num5:” << num5 << endl;
return ;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值