15、lambda表达式、右值引用、移动语义

前言

返回值后置

auto 函数名 (形参表) ->decltype(表达式)

lambda表达式

lambda表达式的名称是一个表达式 (外观类似函数),但本质绝非如此

语法规则

[捕获表] (参数表) 选项 -> 返回类型
{
函数体;
}

lambda表达式的本质

  • lambda表达式本质其实是一个类
  • 并且最终返回值为这个类的对象
  • 因此对lambda表达式的调用就是该对象的函数操作符的调用

简写

  • 可以没有返回值类型,将根据return推断
  • 如果连return也没有,则返回值为void
  • 参数为void可以省略不写

捕获表

  • []:不捕获任何外部变量
  • [variable] : 捕获外部变量的值(具备只读属性)
  • [&variable]: 按引用捕获,指定的外部变量
  • [this]: 捕获this指针,访问外部对象的成员
  • [=]: 按值捕获所有的外部变量,也包括this
  • [&]: 按引用捕获所有的外部变量,也包括this
  • [=,&variable]: 按值捕获所有的外部变量包括this,但是指定的外部变量按引用捕获
  • [&,=variable]: 按引用捕获所有的外部变量,也包括 this,但是指定的外部变量按值捕获
// lambda表达式
#include <iostream>
#include <typeinfo>
using namespace std;

int Max(int x, int y){
    return x > y ? x : y;
}

int main( void ){
    int a = 10, b = 20;

    cout << Max(a,b) << endl;;
    
    auto f = [](int x, int y)->int{ return x > y ?  x : y; };
    // 编译器根据lambda表达式(1)生成一个类 (2)类内定义函数操作符函数 (3)返回这个类的匿名对象
    /*
        class Z4mainEUliiE_{
        public:
             int operator()(int x, int y){
                  return x > y ?  x : y;
             }
        };
        auto f = Z4mainEUliiE_{};
    */
    cout << "f的类型:" << typeid(f).name() << endl;
    cout << f(a,b) << endl; // f.operator()(a,b)

    // lambda表达式可以没有返回值类型,根据return判断
    cout << [](int x, int y) { return x+y; }(a,b) << endl;
    /*
         class X{
         public:
             auto operator()(int x, int y)->decltype(x+y){
                return x + y;
             }
         };
         cout << X{}(a,b) << endl; // cout << X{}.operator()(a,b) << endl;
    */ 

    // lambda表达式可以没有返回类型,也没有retrun语句,返回类型为void
    [](int x, int y){ cout << x << ' ' << y << endl; }(a,b);
    /*
       class XX{
       public:
            void operator()(int x, int y){
                cout << x << ' ' << y << endl;
            }
       };
       XX{}(a,b); // XX{}.operator()(a,b)
    */
    // 如果没有形参,可以省略不写
    []{ cout << "无聊" << endl;}();
    /*
         class XXXX{
         public:
              void operator(){
                cout << "无聊" << endl;
              } 
         };
         XXXX{}();  // XXXX().operator()()
     */ 
    return 0; 
} 

// lambda表达式 -- 捕获表(捕获lambda表达式外部的变量信息)
#include <iostream>
#include <typeinfo>
using namespace std;



int a = 10;

class Y{
public:
    void foo(/* Y* this */ int c = 30 ){
        cout << "-------------[]----------------" << endl;
        [](int d = 40){
            cout << "a=" << a << endl;
            cout << "b=" << b << endl;
//          cout << "c=" << c << endl; // error
            cout << "d=" << d << endl;
//          cout << "e=" << e << endl; // error
        }();
        /*
            class X{
            public:
                void operator()(int d = 40)){
                     cout << "a=" << a << endl;
                     cout << "b=" << b << endl;
                 //  cout << "c=" << c << endl; // error
                     cout << "d=" << d << endl;
                 //  cout << "e=" << this->e << endl; // error
                }
            };
            X{}();

         */

        cout << "-------------[c]----------------" << endl;
        // 捕获外部变量的值
        [c](int d = 40){ cout << "c=" << /*++*/c << endl; }();
         /* 
            class XX{
            public:
                XX(int m):c(m){} //这里的c并不是foo函数的形参,而是XX类的一个成员变量
                void operator()(int d = 40){ 
                    cout << "c=" << c << endl; // //这里的c并不是foo函数的形参,而是XX类的一个成员变量
                }
            private:
                const int c; //这里的c并不是foo函数的形参,而是XX类的一个成员变量
            };
            XX{c}(); // 这里的c是foo函数的形参c   XX(c).operator()()
         */
        cout << "-------------[&c]----------------" << endl;
        [&c](int d = 40){ cout << "c=" << ++c << endl; }();


        cout << "-------------[&c]----------------" << endl;
        [this](int d = 40){ cout << "e=" << e << endl; }();
    }

private:
    static int b;
    int e;
};

int Y::b = 20;

int main( void ){
    Y y;
    y.foo();
    return 0; 
} 

右值引用

左值 和 右值

  • 可以“取”地址的值就是左值,左值通常具名
  • 不可“取”地址的值就是右值,右值通常匿名
    在这里插入图片描述

左值引用 和 右值引用

  • 左值引用只能引用左值,不能引用右值
int a;
int& b = a; // OK
int c;
int& d = a + c; // ERROR
  • 右值引用只能引用右值,不能引用左值
int&& e = a + c;// OK
int&& f = a; // ERROR
  • 常左值引用,既能引用左值,也能引用右值
const int& g = a + c; // OK
const int& h = a; // OK

没有必要有常右值引用,因为常右值引用,完全可以被常左值引用替代

// 左值/右值    左值引用/右值引用
#include <iostream>
using namespace std;

int foo( ) {
    int m=888;
    return m;
}

int main( void ) {
// 当前作用域的生命期
// 具名内存-->能够取址-->左值|非常左值(无const修饰)
//                           |常左值  (有const修饰)
    int a = 10;
    int& ra = a; // ok
    const int& cra = a; // ok

    const int b = 10;
//  int& rb = b; // error
    const int& crb = b; // ok

// 语句级生命期(引用可以延长右值的生命期)
// 匿名内存-->不能取址-->右值|直接更改右值毫无意义(98/03标准给出结论)
//                           | 11标准认为给了真名就可以改

    const int& ri = 10; 
    int&& rri  = 10; 

    const int& rf = /*|888|*/foo( ); // (1)分配一块内存空间  (2)生成跳转指令
    int&& rrf = foo();
    return 0;
}

//左值引用/右值引用
#include <iostream>
using namespace std;


int main( void ) {
    int a,c;

    // 左值引用只能引用左值,不能引用右值
    int& b = a;  // ok
//  int& d = a + c; // error
   
    // 右值引用只能引用右值,不能引用左值
    int&& e = a + c; // ok
    e = 666;         // ok 通过右值引用不会丧失修改目标内存的权限
//  int&& f = a;     // error
  
    // 常左值引用(万能引用),既能引用左值,也能引用右值
    const int& g = a;     // ok
    const int& h = a + c; // ok
//  g = 666;  // error 但是通过常左值引用会丧失修改目标内存的权限
    return 0;
}

移动语义

资源的转移 代替 资源的重建

保证功能正确的情况下,做到性能提升

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

供应链管理的“牛鼻子”在哪里?

什么是供应链管理&#xff1f; 有个定义&#xff1a;供应链管理是使以核心企业为中心的供应链运作达到最优化&#xff0c;以最小的成本&#xff0c;让供应链从采购开始&#xff0c;到满足最终顾客的所有过程&#xff0c;包括物流、信息流、单证流、资金流等均能高效率运作&…

Windows 安全基础——NetBIOS篇

Windows 安全基础——NetBIOS篇 1. NetBIOS简介 NetBIOS&#xff08;Network Basic Input/Output System, 网络基本输入输出系统&#xff09;是一种接入服务网络的接口标准。主机系统通过WINS服务、广播及lmhosts文件多种模式&#xff0c;把NetBIOS名解析对应的IP地址&#xf…

3篇EI论文联合复现:基于数据驱动的综合能源系统多阶段分布鲁棒优化调度程序代码!

本程序参考了3篇电力系统TOP-EI期刊&#xff0c;将目前的热点研究数据驱动结合综合综合能源系统&#xff0c;利用分布鲁棒处理不确定性问题&#xff0c;程序中算例丰富&#xff0c;注释清晰&#xff0c;干货满满&#xff0c;小编非常推荐这个程序&#xff0c;下面对程序代码详细…

【代码+案例】详解SPC相关控制图原理及逻辑代码

Xbar-R图&#xff1a;用于监控样本均值和范围&#xff0c;适合小样本量。Xbar-S图&#xff1a;类似Xbar-R图&#xff0c;但适用于大样本量。p图&#xff1a;用于监控一定时间或样本量内的缺陷比率。np图&#xff1a;类似p图&#xff0c;但用于固定样本量。u图&#xff1a;用于监…

机器学习算法(9)——集成技术(Bagging——随机森林分类器和回归)

一、说明 在这篇文章&#xff0c;我将向您解释集成技术和著名的集成技术之一&#xff0c;它属于装袋技术&#xff0c;称为随机森林分类器和回归。 集成技术是机器学习技术&#xff0c;它结合多个基本模块和模型来创建最佳预测模型。为了更好地理解这个定义&#xff0c;我们需要…

【C++11(三)】智能指针详解--RAII思想循环引用问题

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; C11 1. 前言2. 为什么要有智能指针?3. RAII思想…

.NET 材料检测系统崩溃分析

Windbg 分析 1. 到底是哪里的崩溃 一直跟踪我这个系列的朋友应该知道分析崩溃第一个命令就是 !analyze -v &#xff0c;让windbg帮我们自动化异常分析。 0:033> !analyze -v CONTEXT: (.ecxr) rax00000039cccff2d7 rbx00000039c85fc2b0 rcx00000039cccff2d8 rdx000000000…

水库大坝安全监测参数与设备

智慧水利中&#xff0c;水库大坝的安全监测必不可少。做好水库大坝的安全监测&#xff0c;是确保水库大坝结构安全和预防灾害的重要手段。对于预防灾害、保护人民生命财产安全、优化工程管理、改进工程设计、保护环境资源和提高公众信任等方面有着重要的意义。 水利水库大坝安全…

酷滴科技出席浦发银行第七届国际金融科技创新大赛

12月7日&#xff0c;浦发银行全球金融科技创新大赛在上海展开决赛。本届大会以“科技金融&#xff0c;激发创新力量”为主题&#xff0c;聚焦金融行业数字化转型过程中的痛点与难点&#xff0c;旨在探讨新时代下金融科技的新角色、新机遇以及新挑战。酷滴科技CEO张沈分享了酷滴…

花椒油行业分析:预计2025年市场规模将达到350亿元以上

近年来&#xff0c;麻辣口味在全国普及&#xff0c;随着火锅、川菜、烤鱼、串串香等麻辣餐饮的发展与扩张&#xff0c;花椒的市场需求也日益增长。实际上&#xff0c;花椒的应用远不止于餐饮市场&#xff0c;其背后是庞大而复杂的产业链。 在政策扶持以及日益旺盛的市场需求(尤…

MySQL - 聚簇索引和非聚簇索引,回表查询,索引覆盖,索引下推,最左匹配原则

聚簇索引和非聚簇索引 聚簇索引和非聚簇索引是 InnoDB 里面的叫法 一张表它一定有聚簇索引&#xff0c;一张表只有一个聚簇索引在物理上也是连续存储的 它产生的过程如下&#xff1a; 表中有无有主键索引&#xff0c;如果有&#xff0c;则使用主键索引作为聚簇索引&#xff1b;…

Java - 线程间的通信方式

线程通信的方式 线程中通信是指多个线程之间通过某种机制进行协调和交互 线程通信主要可以分为三种方式&#xff0c;分别为共享内存、消息传递和管道流。每种方式有不同的方法来实现 共享内存&#xff1a;线程之间共享程序的公共状态&#xff0c;线程之间通过读-写内存中的公…

成都工业学院Web技术基础(WEB)实验六:ECMAScript基础语法

写在前面 1、基于2022级计算机大类实验指导书 2、代码仅提供参考&#xff0c;前端变化比较大&#xff0c;按照要求&#xff0c;只能做到像&#xff0c;不能做到一模一样 3、图片和文字仅为示例&#xff0c;需要自行替换 4、如果代码不满足你的要求&#xff0c;请寻求其他的…

吉祥物IP怎么结合动捕设备应用在线下活动?

一个好的吉祥物IP&#xff0c;不仅可以为品牌带来传播效果和形象具体化的价值&#xff0c;还可以带来一系列的商业利益。 当吉祥物IP接入惯性动作捕捉系统&#xff0c;即可由真人幕后穿戴动捕设备进行实时驱动&#xff0c;可以通过虚拟数字人直播、数字人短视频、数字人线下活动…

如何在Ubuntu的Linux系统上安装nacos的2.3.0版本

官方网址链接 home (nacos.io)Nacos 快速开始github代码仓库简单介绍 Nacos是阿里巴巴的产品&#xff0c;现在是SpringCloud中的一个组件&#xff0c;其可以用于服务发现和服务健康监测、动态配置服务、动态DNS服务、服务及其元数据管理。安装包下载地址&#xff1a; Releases …

Python3开发环境的搭建

1&#xff0c;电脑操作系统的确认 我的是win10、64位的&#xff0c;你们的操作系统可自寻得。 2&#xff0c;Python安装包的下载 &#xff08;1&#xff09;浏览器种输入网址&#xff1a;https://www.python.org 选择对应的系统&#xff08;我的是win10/64位) &#xf…

面试 JVM 八股文五问五答第一期

面试 JVM 八股文五问五答第一期 作者&#xff1a;程序员小白条&#xff0c;个人博客 相信看了本文后&#xff0c;对你的面试是有一定帮助的&#xff01; ⭐点赞⭐收藏⭐不迷路&#xff01;⭐ 1.JVM内存布局 Heap (堆区&#xff09; 堆是 OOM 故障最主要的发生区域。它是内存…

CRM系统的这些功能助您高效管理客户

客户管理可以理解为企业收集并利用客户信息&#xff0c;满足客户的需求&#xff0c;从而提升客户价值的过程。CRM系统一直被誉为客户管理的“神器”&#xff0c;下面我们就来说说CRM系统有哪些功能可以管理客户&#xff1f; 1、客户信息管理 CRM可以帮助企业收集客户的基本信…

C++11(下)

可变参数模板 C11的新特性可变参数模板能够创建可以接受可变参数的函数模板和类模板. 相比C98/03, 类模版和函数模版中只能含固定数量的模版参数, 可变模版参数无疑是一个巨大的改进, 然而由于可变模版参数比较抽象, 使用起来需要一定的技巧, 所以这块还是比较晦涩的.掌握一些基…

《Spring Cloud Alibaba 从入门到实战》分布式配置

分布式配置 1、简介 Nacos 提供用于存储配置和其他元数据的 key/value 存储&#xff0c;为分布式系统中的外部化配置提供服务器端和客户端支持。 Spring Cloud Alibaba Nacos Config 是 Config Server 和 Client 的替代方案&#xff0c;在特殊的 bootstrap 阶段&#xff0c;…