C++11 -表达式/包装器

news2025/4/1 12:54:44

1. lambda 表达式各部分说明

  • [capture-list]:捕捉列表,该列表总是出现在 lambda 函数的开始位置,编译器根据 [] 来判断接下来的代码是否为 lambda 函数,捕捉列表能够捕捉上下文中的变量供 lambda 函数使用。
  • (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以连同 () 一起省略。
  • mutable:默认情况下,lambda 函数总是一个 const 函数,mutable 可以取消其常量性。使用该修饰符时,参数列表不可省略 (即使参数为空)。
  • ->return-type:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回值时此部分可省略。返回值类型明确情况下,也可省略,由编译器对返回类型进行推导。
  • {statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获到的变量。

2. 捕获列表说明

捕获列表描述了上下文中那些数据可以被 lambda 使用,以及使用的方式传值还是传引用。

  • [var]:表示值传递方式捕捉变量 var。
  • [=]:表示值传递方式捕获所有父作用域中的变量 (包括 this)。
  • [&var]:表示引用传递捕捉变量 var。
  • [&]:表示引用传递捕捉所有父作用域中的变量 (包括 this)。
注意:

a. 父作用域指包含 lambda 函数的语句块。
b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割。比如:[=, &a, &b]:以引用传递的方式捕捉变量 a 和 b,值传递方式捕捉其他所有变量;[&, a, this]:值传递方式捕捉变量 a 和 this,引用方式捕捉其他变量。
c. 捕捉列表不允许变量重复传递,否则就会导致编译错误。比如:[=, a]:= 已经以值传递方式捕捉了所有变量,捕捉 a 重复。
d. 在块作用域以外的 lambda 函数捕捉列表必须为空。
f. lambda 表达式之间不能相互赋值,即使看起来类型相同。

代码演示:

void test_lambda()
{
    vector<Goods> G{ {"apple",1},{"banana",2} };
    /*sort(G.begin(), G.end(),comUp());*/
    sort(G.begin(), G.end(), [](const Goods& g1, const Goods& g2)->bool {return g1.price > g2.price; });
    for (auto e : G)
    {
        cout << e._name << ":" << e.price << endl;
    }
    //lambda运用!可以把它看成一个对象!它的底层其实还是一个仿函数!
    auto f1 = [](int x, int y) {int ret = x + y; cout << ret << endl; return 0; };
    f1(1, 2);
    auto f2 = [](int x)
        {
            cout << x << endl;
            return 0;
        };
    f2(0);
    //捕获列表的使用!
    // []就是这个括号里面可以随意调用同一个作用域下的,任意的变量,但是要记住,它调用的时候[&x,&y],加了引用这个属于引用捕捉
    // 此时x和y是默认为const类型,当然加了引用就不加mutable
    //想要解决这个const就加一个mutable
    int x = 1; int y = 0;
    auto f0 = [&x,&y]() mutable {int ret = x + y; cout << ret << endl; return 0; };

    //捕获全局块作用域
    auto ff = [=]() {cout << x << endl; };
    //捕获后单独修改个
    auto fff = [=, &y]() {cout << x << endl; y++; cout << y << endl; };
    //放在作成员函数的时候可以捕捉整个父类作用域!

2.包装器

1. std::function

std::function 是 C++ 标准库提供的一个通用多态函数包装器,它可以存储、复制和调用任何可调用对象,比如普通函数、成员函数、lambda 表达式、函数对象等。

void swap_1(int& x, int& y)
{
    cout << "swap" << endl;
}

void test_functional()
{
    包装器-
    int x = 1; int y = 0;
    auto f1 = [&x, &y]() mutable {int ret = x + y; cout << ret << endl; return 0; };
    comDown dw();
    function<void(int&, int&)> f_1 = swap_1;
    f_1(x,y);
    function<bool(const Goods&, const Goods&)> fff = dw();
   /* fff(x, y);*/
   /* Goods g1(10);
    Goods g2(20);*/
}

2. std::bind

std::bind 用于将可调用对象与其参数进行绑定,生成一个新的可调用对象。它可以预先绑定部分参数,也能调整参数的顺序。

void test_111()
{
    int res = sum(1, 2, 3, 4, 5);
    cout << res << endl;
    
}
int f(int a, int b)
{
    return a + b;
}

struct Functor
{
public:
    int operator() (int a, int b)
    {
        return a + b;
    }
};

class Plus
{
public:
    static int plusi(int a, int b)//静态成员没有this指针!
    {
        return a + b;
    }

    double plusd(double a, double b)
    {
        return a + b;
    }
};

//function属于类模版 而bind属于函数模版!
int main()
{
    /*ShowList(1);
    ShowList(1, 'A');
    ShowList(1, 'A', std::string("sort"));*/

  /*  test_lambda();*/
    // 函数名(函数指针)
    //std::function<int(int, int)> func1 = f;
    //cout << func1(1, 2) << endl;

     函数对象
    //std::function<int(int, int)> func2 = Functor();
    //cout << func2(1, 2) << endl;
     lamber表达式
    //std::function<int(int, int)> func3 = [](const int a, const int b) {return a + b; };
    //cout << func3(1, 2) << endl;

     类的成员函数//记住普通函数名就是地址所以看见普通函数没有加引用,但是成员函数是名并不是地址,所以需要加引用符号和类域!
    //std::function<int(int, int)> func4 = &Plus::plusi;
    //cout << func4(1, 2) << endl;

    //std::function<double(Plus, double, double)> func5 = &Plus::plusd;
    //cout << func5(Plus(), 1.1, 2.2) << endl;
    Plus()匿名对象属于右值,右值不能取地址,所以不能加引用!

    //bind应用-----------------
    //调整参数个数,有些参数可能就被写死了,
    /*auto fit = bind(f, 5, placeholders::_1);
    int ret=fit(2);
    cout << ret << endl;*/
    test_111();

    return 0;
}

3. 智能指针作为包装器

智能指针(如 std::unique_ptrstd::shared_ptr 和 std::weak_ptr)也是一种包装器,它们用于管理动态分配的内存,能够自动释放内存,避免内存泄漏。(后续再补充)

class MyClass {
public:
    MyClass() { std::cout << "MyClass constructor" << std::endl; }
    ~MyClass() { std::cout << "MyClass destructor" << std::endl; }
    void doSomething() { std::cout << "Doing something..." << std::endl; }
};

int main() {
    // 使用 std::unique_ptr 包装 MyClass 对象
    std::unique_ptr<MyClass> ptr = std::make_unique<MyClass>();
    ptr->doSomething();

    return 0;
}   

3.万能模版:

这个万能模版万能在了不管你传入的参数是右值还是左值都可以使用。但是要注意的是,一定要注意在调用的时候是嵌套的而且嵌套的时候需要使用forward<>()它是可以帮你自动匹配你是左值还是右值!

template<class T>
void Print(T&& t)
{
    cout << t << endl;
}


//模版里面的万能引用:
template<class T>
void PerfectForward(T&& t)//在这个参数这里,你给它传左右值都可以!
{
    //这里的forward叫做完美转发,它可以让你传入的参数,也可以自动配对!
    Print(forward<T>(t));//叫做完美转换!
}

4.总结

首先说一下,lambda表达式,对于这个表达式让我们可以更加方便的使用,减少对一些函数的编写,完全可以代替仿函数和一些简单函数,但是一定要熟练使用的格式,在这里再提一下decltype,它的使用是可以带到参数里面的!切记,你用auto 出来的其实可以理解为一个新的函数,所以当你cout或者干什么的时候,是需要用函数那样用的 :cout<<f();

其次就是bind,使用它的时候要注意一些参数的编写,第一个不能少了函数地址,其次就是参数是可以单个固定,未固定的参数需要用placeholders用占位符标记,你用几个占位符,你调用刚刚封装的新的函数时候就要输入几个参数!

然后是function<返回类型(参数)> 新函数名=旧函数。注意它可以使用的对象都有哪些!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2324343.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

VectorBT:使用PyTorch+LSTM训练和回测股票模型 进阶二

VectorBT&#xff1a;使用PyTorchLSTM训练和回测股票模型 进阶二 本方案基于LSTM神经网络构建多时间尺度股票收益率预测模型&#xff0c;结合VectorBT进行策略回测。核心原理是通过不同时间窗口&#xff08;5/10/20/30日&#xff09;捕捉股价的短期、中期、长期模式&#xff0c…

蓝桥杯 第十二天 819 递增序列

注意注意&#xff1a;不考虑左上的情况&#xff0c;因为题目给的样例没有 public static int is1(char ch[][],int m,int n){int ans0;for (int i0;i<m;i){//起始点在哪for (int j0;j<n;j){int add1;while(jadd<n){if(ch[i][j]<ch[i][jadd]) ans; //横add;}add1…

【YOLOv11】目标检测任务-实操过程

目录 一、torch环境安装1.1 创建虚拟环境1.2 启动虚拟环境1.3 安装pytorch1.4 验证cuda是否可用 二、yolo模型推理2.1 下载yolo模型2.2 创建模型推理文件2.3 推理结果保存路径 三、labelimg数据标注3.1 安装labelimg3.2 解决浮点数报错3.3 labelimg UI界面介绍3.4 数据标注案例…

C++_STL之vector篇

一、vector的常见用法 注&#xff1a;C中若使用vector需包含头文件<vector>. 1.vector的构造函数 int n 10,ret1;vector<int> nums(n,ret); //n表示vector初始的容量 ret表示vector中初始化的值for (auto e : nums)cout << e << " "; 扩展…

sqli-labs靶场 less 9

文章目录 sqli-labs靶场less 9 时间盲注 sqli-labs靶场 每道题都从以下模板讲解&#xff0c;并且每个步骤都有图片&#xff0c;清晰明了&#xff0c;便于复盘。 sql注入的基本步骤 注入点注入类型 字符型&#xff1a;判断闭合方式 &#xff08;‘、"、’、“”&#xf…

【Golang】第八弹----面向对象编程

&#x1f525; 个人主页&#xff1a;星云爱编程 &#x1f525; 所属专栏&#xff1a;Golang &#x1f337;追光的人&#xff0c;终会万丈光芒 &#x1f389;欢迎大家点赞&#x1f44d;评论&#x1f4dd;收藏⭐文章 前言&#xff1a;Go语言面向对象编程说明 Golang也支持面向对…

java基础以及内存图

java基础 命名&#xff1a; 大驼峰&#xff1a;类名 小驼峰&#xff1a;变量名方法名等其他的 全部大写&#xff1a;常量名字.. // 单行注释 /**/ 多行注释 变量类型 变量名 一、基本类型&#xff08;8个&#xff09; 整数&#xff1a;byte-8bit short-16bit int 32-b…

【嵌入式学习3】TCP服务器客户端 - UDP发送端接收端

目录 1、TCP TCP特点 TCP三次握手&#xff08;建立TCP连接&#xff09;&#xff1a; TCP四次握手【TCP断开链接的时候需要经过4次确认】&#xff1a; TCP网络程序开发流程 客户端开发&#xff1a;用户设备上的程序 服务器开发&#xff1a;服务器设备上的程序 2、UDP 为…

Linux之基础知识

目录 一、环境准备 1.1、常规登录 1.2、免密登录 二、Linux基本指令 2.1、ls命令 2.2、pwd命令 2.3、cd命令 2.4、touch命令 2.5、mkdir命令 2.6、rmdir和rm命令 2.7man命令 2.8、cp命令 2.9、mv命令 2.10、cat命令 2.11、echo命令 2.11.1、Ctrl r 快捷键 2…

llamafactory微调效果与vllm部署效果不一致如何解决

在llamafactory框架训练好模型之后&#xff0c;自测chat时模型效果不错&#xff0c;但是部署到vllm模型上效果却很差 这实际上是因为llamafactory微调时与vllm部署时的对话模板不一致导致的。 对应的llamafactory的代码为 而vllm启动时会采用大模型自己本身设置的对话模板信息…

WebSocket通信的握手阶段

1. 客户端建立连接时&#xff0c;通过 http 发起请求报文&#xff0c;报文表示请求服务器端升级协议为 WebSocket&#xff0c;与普通的 http 请求协议略有区别的部分在于如下的这些协议头&#xff1a; 上述两个字段表示请求服务器端升级协议为 websocket 协议。 2. 服务器端响…

分布式ID服务实现全面解析

分布式ID生成器是分布式系统中的关键基础设施&#xff0c;用于在分布式环境下生成全局唯一的标识符。以下是各种实现方案的深度解析和最佳实践。 一、核心需求与设计考量 1. 核心需求矩阵 需求 重要性 实现难点 全局唯一 必须保证 时钟回拨/节点冲突 高性能 高并发场景…

dom0运行android_kernel: do_serror of panic----failed to stop secondary CPUs 0

问题描述&#xff1a; 从日志看出,dom0运行android_kernel&#xff0c;刚开始运行就会crash,引发panic 解决及其原因分析&#xff1a; 最终问题得到解决&#xff0c;发现是前期在调试汇编阶段代码时&#xff0c;增加了汇编打印的指令&#xff0c;注释掉这些指令,问题得到解决。…

HarmonyOS NEXT——【鸿蒙原生应用加载Web页面】

鸿蒙客户端加载Web页面&#xff1a; 在鸿蒙原生应用中&#xff0c;我们需要使用前端页面做混合开发&#xff0c;方法之一是使用Web组件直接加载前端页面&#xff0c;其中WebView提供了一系列相关的方法适配鸿蒙原生与web之间的使用。 效果 web页面展示&#xff1a; Column()…

优选算法的慧根之翼:位运算专题

专栏&#xff1a;算法的魔法世界 个人主页&#xff1a;手握风云 一、位运算 基础位运算 共包含6种&(按位与&#xff0c;有0就是0)、|(按位或有1就是1)、^(按位异或&#xff0c;相同为0&#xff0c;相异为1)、~(按位取反&#xff0c;0变成1&#xff0c;1变成0)、<<(左…

图论问题集合

图论问题集合 寻找特殊有向图&#xff08;一个节点最多有一个出边&#xff09;中最大环路问题特殊有向图解析算法解析步骤 1 &#xff1a;举例分析如何在一个连通块中找到环并使用时间戳计算大小步骤 2 &#xff1a;抽象成算法注意 实现 寻找特殊有向图&#xff08;一个节点最多…

【数据结构】栈 与【LeetCode】20.有效的括号详解

目录 一、栈1、栈的概念及结构2、栈的实现3、初始化栈和销毁栈4、打印栈的数据5、入栈操作---栈顶6、出栈---栈顶6.1栈是否为空6.2出栈---栈顶 7、取栈顶元素8、获取栈中有效的元素个数 二、栈的相关练习1、练习2、AC代码 个人主页&#xff0c;点这里~ 数据结构专栏&#xff0c…

Redis设计与实现-哨兵

哨兵模式 1、启动并初始化sentinel1.1 初始化服务器1.2 使用Sentinel代码1.3 初始化sentinel状态1.4 初始化sentinel状态的master属性1.5 创建连向主服务器的网络连接 2、获取主服务器信息3、获取从服务器的信息4、向主从服务器发送信息5、接受主从服务器的频道信息6、检测主观…

C++进阶——封装哈希表实现unordered_map/set

与红黑树封装map/set基本相似&#xff0c;只是unordered_map/set是单向迭代器&#xff0c;模板多传一个HashFunc。 目录 1、源码及框架分析 2、模拟实现unordered_map/set 2.1 复用的哈希表框架及Insert 2.2 iterator的实现 2.2.1 iteartor的核心源码 2.2.2 iterator的实…

【算法day25】 最长有效括号——给你一个只包含 ‘(‘ 和 ‘)‘ 的字符串,找出最长有效(格式正确且连续)括号子串的长度。

32. 最长有效括号 给你一个只包含 ‘(’ 和 ‘)’ 的字符串&#xff0c;找出最长有效&#xff08;格式正确且连续&#xff09;括号子串的长度。 https://leetcode.cn/problems/longest-valid-parentheses/ 2.方法二&#xff1a;栈 class Solution { public:int longestValid…