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

news2024/11/27 10:45:26

前言

返回值后置

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;
}

移动语义

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

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

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

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

相关文章

Windows汇编调用printf

VS2022 汇编 项目右键 生成依赖项 生成自定义 勾选masm 链接器 高级 入口点 main X86 .686 .model flat,stdcall option casemap:none includelib ucrt.lib includelib legacy_stdio_definitions.libEXTERN printf:proc.data szFormat db %s,0 szStr db hello,0.code main…

AI 绘画 | Stable Diffusion 艺术字与光影效果

前言 这篇文章教会你如何使用Stable Diffusion WEB UI扩展插件ControlNet控制光影模型实现艺术字与图片的光影效果。艺术字主要原理是用到了Depth (深度)算法和模型,光影效果是用到了control_v1p_sd15_brightness(亮度)和control_v1p_sd15_illumination(光亮)两个模型其中…

力扣每日一题day32[104. 二叉树的最大深度]

给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&#xff1a;root [1,null,2] 输出…

Spring Boot 3 集成 Druid 连接池详解

在现代的Java应用中&#xff0c;使用一个高效可靠的数据源是至关重要的。Druid连接池作为一款强大的数据库连接池&#xff0c;提供了丰富的监控和管理功能&#xff0c;成为很多Java项目的首选。本文将详细介绍如何在Spring Boot 3项目中配置数据源&#xff0c;集成Druid连接池&…

普冉(PUYA)单片机开发笔记(7): ADC-轮询式多路采样

概述 应用中经常会有使用单片机进行模数转换的需求。PY32F003 具有 1 个 12 位的模拟数字转换器&#xff08;ADC&#xff09;&#xff0c;今天我们一起来使用一下这个 ADC。 数据手册中对 ADC 简介如下。 SAR ADC&#xff1a;逐次逼近式 ADC&#xff0c;原理参见“参考链接&a…

六何分析法分析uniApp

一、什么是 uniApp&#xff08;What&#xff09; uni-app 是一个使用 Vue.js 开发所有前端应用的框架&#xff0c;开发者编写一套代码&#xff0c;可发布iOS、Android、H5、以及各种小程序( 微信/支付宝/百度/头条/00/钉钉/淘宝)、快应用等多个平台。uni-app 在手&#xff0c;…

AI隆重软件,AI原创文章隆重软件

随着信息量的急剧增加&#xff0c;许多写作者、网站管理员和内容创作者们纷纷感受到了文章降重的压力。原始文本的降重&#xff0c;需要保留关键信息的同时避免重复&#xff0c;这是一项既繁琐又耗时的任务。 改写软件的批量降重功能 147SEO改写软件在降重领域的卓越表现主要体…

小目标检测模型设计的一点思考

1. 小目标的特性 目标之间的交叠概率比较低&#xff0c;即使有交叠&#xff0c;其IoU多数情况下也是比较小的 AI-TOD Tiny Person Dateset 小目标自身的纹理显著度有强弱区别&#xff0c;但是总体来说纹理特征都较弱&#xff0c;很多时候需要借助一定的图像上下文来帮助确认 …

自动驾驶学习笔记(十七)——视觉感知

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《Apollo 社区开发者圆桌会》免费报名—>传送门 文章目录 前言 分类 目标检测 语义分割 实例分割 …

Angular 从零开始,快速上手

Angular 从零开始&#xff0c;快速上手 一、AngularJS 简介1.1 AngularJS 的背景1.2 AngularJS 的简介1.3 AngularJS 概念概述1.4 AngularJS 特性1.5 AngularJS 和 JQuery 比较 二、安装 AngularJS2.1 方式一&#xff1a;使用在线 cdn2.2 方式二&#xff1a;使用依赖管理工具 n…

三. LiDAR和Camera融合的BEV感知算法-BEV-SAN

目录 前言0. 简述1. 算法动机&开创性思路2. 主体结构3. 损失函数4. 性能对比总结下载链接参考 前言 自动驾驶之心推出的《国内首个BVE感知全栈系列学习教程》&#xff0c;链接。记录下个人学习笔记&#xff0c;仅供自己参考。 本次课程我们来学习下课程第三章——LiDAR和Ca…

弧形导轨的结构特点

弧形导轨&#xff0c;顾名思义就是滑座沿着导轨做弧线运动&#xff0c;在工业自动化的许多运用中&#xff0c;直线运动很遍及&#xff0c;但是有些运用&#xff0c;需求弧线运动&#xff0c;或者两个相交或平行的直线运动&#xff0c;需求通过弧线运动衔接起来&#xff0c;那么…

qt可以详细写的项目或技术

1.QT 图形视图框架 2.QT 模型视图结构 3.QT列表显示大量信息 4.QT播放器 5.QT 编解码 6.QT opencv

高级Linux监控堡垒机学习指南

高级Linux监控堡垒机学习指南 在现代复杂的网络环境中&#xff0c;安全性和监控是系统管理的核心关注点。Linux监控堡垒机作为一种安全管理工具&#xff0c;不仅可以追踪系统活动&#xff0c;还能提供对服务器和网络资源的高级监控。本文将深入探讨高级Linux监控堡垒机的学习内…

windows端口被占用怎么办 怎么关闭那个占用的端口

目录 这是出现的情况怎么解决了1.请打开这玩意2.输入下面---查询 先关端口的信息根据id获得服务 上图的8888 对应的ip 上图就是134243.杀死进程134244.重启服务 这是出现的情况 怎么解决了 1.请打开这玩意 2.输入下面—查询 先关端口的信息 netstat -ano过滤信息查询想要的端…

用 Python 自动创建 Markdown 表格

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com Markdown表格是文档中整理和展示数据的重要方式之一。然而&#xff0c;手动编写大型表格可能会费时且容易出错。本文将介绍如何使用Python自动创建Markdown表格&#xff0c;通过示例代码详细展示各种场景下的创建…

Python列表的排序方法:从基础到高级

更多Python学习内容&#xff1a;ipengtao.com 大家好&#xff0c;我是彭涛&#xff0c;今天为大家分享 Python列表的排序方法&#xff1a;从基础到高级&#xff0c;全文3400字&#xff0c;阅读大约10分钟。 在Python中&#xff0c;列表是一种常用的数据结构&#xff0c;而对列表…

排序算法之六:快速排序(非递归)

快速排序是非常适合使用递归的&#xff0c;但是同时我们也要掌握非递归的算法 因为操作系统的栈空间很小&#xff0c;如果递归的深度太深&#xff0c;容易造成栈溢出 递归改非递归一般有两种改法&#xff1a; 改循环借助栈&#xff08;数据结构&#xff09; 图示算法 不是…

P1317 低洼地题解

题目 一组数&#xff0c;分别表示地平线的高度变化。高度值为整数&#xff0c;相邻高度用直线连接。找出并统计有多少个可能积水的低洼地&#xff1f; 如图&#xff1a;地高变化为 [0,1,0,2,1,2,0,0,2,0]。 输入输出格式 输入格式 两行&#xff0c;第一行n, 表示有n个数。第…

【Unity动画】什么是任意状态(Any state)

&#xff08;Any state&#xff09;可以从某个状态A直接切换到另一个状态 B\C\D\E\F 比如A到C的过渡&#xff0c;直接设置从Any state 到C的过渡线触发参数即可。而不需要让A到C直接在连接&#xff0c;同样&#xff0c;B到C之间也无需直接链接。 这样设计是在每一个动画之间都…