C++ Primer 学习笔记:泛型算法入门 定制操作(函数指针) && lambda表达式

很多算法是有默认的操作,但是有的时候我们需要特定的操作,比如排序等等,那么STL提供了一个叫做谓词的参数来实现这个功能,其实就是一个函数指针的参数。

一元谓词 && 二元谓词

谓词是一个可以调用的表达式,它的返回结果是一个能够用作条件的值,标准库算法所使用的谓词分为一元谓词(unary predicate,也就是它们只能接受一个参数)和二元谓词(binary predicate,也就是它们只能接受两个参数),就是其实接受一个参数的谓语是一元,两个是二元.

lambda表达式

C++11提供了对匿名函数的支持,称为Lambda函数(也叫Lambda表达式). Lambda表达式具体形式如下:

[capture](parameters)->return-type{body}

如果没有参数,空的圆括号()可以省略.返回值也可以省略,如果函数体只由一条return语句组成或返回类型为void的话.形如:

 [capture](parameters){body}

下面举了几个Lambda函数的例子:     

[](int x, int y) { return x + y; } // 隐式返回类型
[](int& x) { ++x; }   // 没有return语句 -> lambda 函数的返回类型是'void'
[]() { ++global_x; }  // 没有参数,仅访问某个全局变量
[]{ ++global_x; }     // 与上一个相同,省略了()

可以像下面这样显示指定返回类型:

[](int x, int y) -> int { int z = x + y; return z; }

捕获列表:lambda表达式的捕获列表精细控制了lambda表达式能够访问的外部变量,以及如何访问这些变量。

捕获值列表,是允许我们在Lambda表达式的函数体中直接使用这些值,捕获值列表能捕获的值是所有在此作用域可以访问的值,包括这个作用域里面的临时变量,类的可访问成员,全局变量。捕获值的方式分两种,一种是按值捕获,一种是按引用捕获。顾名思义,按值捕获是不改变原有变量的值,按引用捕获是可以在Lambda表达式中改变原有变量的值。

[捕获值列表]:

1、空。没有使用任何函数对象参数。
2、=。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
3、&。函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。
4、this。函数体内可以使用Lambda所在类中的成员变量。
5a。将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。
6、&a。将a按引用进行传递。
7a, &b。将a按值进行传递,b按引用进行传递。
8、=,&a, &b。除a和b按引用进行传递外,其他参数都按值进行传递。
9、&, a, b。除a和b按值进行传递外,其他参数都按引用进行传递。

指定返回类型

如果一个lambda体包含return之外的任何语句,则编译器假定此lambda返回void。与其他返回void的函数类似,被推断返回void的lambda不能返回值。
当我们需要为一个lambda定义返回类型时,必须使用尾置返回类型。

比如下面的例子

    vector<int> s;
    for (int i = 0; i < 10; i++)
        s.push_back((i % 2 == 0 ? i : -1));

    transform(s.begin(), s.end(),s.begin(),[](int i) { return i < 0 ? -i : i; });

transform前两个参数表示迭代器的范围,第三个参数表示目的为准,第四个是一个函数指针,上述的写法是没有问题的,但是下面的就有问题了

般情况下,编译器会自动推断出lambda的返回类型, 当lambda函数体内包含不止一个return语句时,编译器就不能推断其返回类型,下面的例子原因是这样的:虽然两个return语句都返回int型,但编译器不能推断出其返回类型,所以该语句会产生编译错误。

    transform(s.begin(), s.end(), s.begin(), [](int i) { if (i < 0) return  -i;else return i; });

这个时候需要使用尾置返回,应该这么做,也即 -> type

    transform(s.begin(), s.end(), s.begin(), [](int i) -> int { if (i < 0) return  -i; else return i; });
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值