C++11&14新标准——Lambdas,decltype

2023-12-18 17:45:32

系列文章目录

C++11&14新标准——Variadic templates(数量不定的模板参数)
C++11&14新标准——Uniform Initialization(统一初始化)、Initializer_list(初始化列表)、explicit
C++11&14新标准—— =delete、=default
C++11&14新标准——模板模板参数(Template Template Parameter)、using
C++11&14新标准——Lambdas,decltype



Lambdas

?? Lambdas即为匿名函数,他的格式一般为:

[ captures ] ( params ) specifiers exception attr -> ret { body }  (1) 
[ captures ] ( params ) -> ret { body }                            (2) 
[ captures ] ( params ) { body }                                   (3) 
[ captures ] { body }                                              (4)                                  

captures: 捕获参数,即Lambdas内会使用到的之前定义的变量。详细格式见下图。

格式意义
[ ]默认不捕获任何变量
[ = ]默认以值捕获所有变量
[ & ]默认以引用捕获所有变量
[ x ]仅以值捕获x变量
[ &x ]仅以引用捕获x变量
[ =, &x ]默认以值捕获所有变量,但以引用捕获x变量
[ &, x ]默认以引用捕获所有变量,但以值捕获x变量
[ this ]通过引用捕获当前对象
[ *this ]通过值捕获当前对象

params:参数列表,Lambdas需要接收的参数。

ret:返回类型,不写的话编译器也可以自己推断。

body:函数体。

specifiers:限定符列表。比如mutable表示会更改捕获参数,const表示不会更改捕获参数。

exception:异常规定。比如noexcept表示不会抛出异常。

attr:属性规定,相当于是一个有一定功能的提醒,例如nodiscard属性告诉编译器,这个lambda表达式的返回值不应该被忽略。如果调用这个lambda并且不使用它的返回值,编译器可能会产生一个警告。

auto lambda = []() [[nodiscard]] {
    return 42;
};

再比如deprecated属性标记了这个lambda表达式已经不推荐使用,并提供了一个字符串消息,指出了替代的推荐用法。如果使用这个lambda,编译器可能会产生一个关于弃用的警告。

auto lambda = []() [[deprecated("Use newFunction() instead")]] {
    // Do something
};

使用例

  1. 定义一个匿名函数
[]{
    std::cout<< "hello world!" <<std::endl;
}
  1. 调用匿名函数
[]{
    std::cout<< "hello world!" <<std::endl;
}();
  1. 传递匿名函数给一个变量,并调用
auto l = []{
    std::cout<< "hello world!" <<std::endl;
};
l();
  1. 带参数列表的匿名函数
auto l = [](const std::string &s){
    std::cout<< s <<std::endl;
};
l("hello world!");
  1. 带捕获参数的匿名函数
int x = 1;
int y = 2;
auto f = [x, &y] {
            std::cout<<"x:" << x << std::endl;
            std::cout<<"y:" << y << std::endl;
            ++y;
            //++x;//Error
         };
x = y = 77;
f(); //输出x:1 ,y:77
f();//输出x:1 ,y:78
std::cout<< "final y: " << y <<std::endl;//final y:79

从这个例子可以看出,捕获参数列表,在定义lambdas的时候就对参数进行捕获,定义是x = 1,捕获参数x以值传递,所以在f中x就为1,哪怕后续x = 77了,f()输出的x仍然为1。但对于y的捕获是以引用传递,定义里y为2,但后续过程中y = 77了,相应的f()中的y也为77。

为什么写++x会报错呢?因为x是以值传递的,相当于权限为onlyread,如果想要改变x的值,就必须加上mutable关键字。y则是以引用传递的,不加mutable也可以变化。

decltype

decltype是c++11定义的一个新关键字,作用是获得对象的类型。
在这里插入图片描述
他有三种主要的应用:

  1. 用于声明返回类型,下面两种格式效果一样。
    在这里插入图片描述
    在这里插入图片描述
  2. 用于元模板编程,通过模板对象获取模板类型。
    在这里插入图片描述
  3. 用于匿名函数,获得匿名函数返回值的类型。

    但用这种方法使用lambdas的时候要注意,如果使用这种方法初始化set,编译器会报错:
std::set<Person,decltype(cmp)> coll();

采用set的默认构造函数,会调用参数类型即lambdas的默认构造函数,但lambdas是没有构造函数和赋值重载,所以不能用这种方式进行初始化。
在这里插入图片描述

文章来源:https://blog.csdn.net/weixin_48956191/article/details/135057659
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。