C/C++ ③ —— C++11新特性

1. 类型推导

1.1 auto

  • auto可以让编译器在编译期就推导出变量的类型
    • auto的使⽤必须⻢上初始化,否则⽆法推导出类型
    • auto在⼀⾏定义多个变量时,各个变量的推导不能产⽣⼆义性,否则编译失败
    • auto不能⽤作函数参数
    • 在类中auto不能⽤作⾮静态成员变量
    • auto不能定义数组,可以定义指针
    • auto⽆法推导出模板参数
    • 在不声明为引⽤或指针时,auto会忽略等号右边的引⽤类型和const(常量)、volatile(易变性)限定
    • 在声明为引⽤或者指针时,auto会保留等号右边的引⽤和cv属性

1.2 decltype

  • ⽤于推导表达式类型,这⾥只⽤于编译器分析表达式的类型,表达式实际不会进⾏运算
  • decltype不会像auto⼀样忽略引⽤和cv属性,decltype会保留表达式的引⽤和cv属性
  • 对于decltype(exp),若exp是表达式,decltype(exp)和exp类型相同;若exp是函数调⽤,decltype(exp)和函数返回值类型相同;若exp是左值,decltype(exp)是exp类型的左值引⽤。
  • auto和decltype配合使用:
template<typename T, typename U>
auto add(T t, U u)->decltype(t + u){return t + u;
}

2. 范围for循环

  • 基于范围的迭代写法,for(变量:对象)表达式:
string str ("some thing");
for(char c : str) cout << c << endl;
  • 对vector中的元素进⾏遍历:
vector<int> arr(5, 100);
for(vector<int>::iterator i = arr.begin(); i != arr.end(); ++i) cout << *i << endl;
for(auto &i : arr) cout << i << endl;

3. 右值引用

3.1 左值和右值

  • 左值:可以放在等号左边,可以取地址并有名字
  • 右值:不可以放在等号左边,不能取地址,没有名字
    • 其定义形式为:Type &&var;其中 Type 表示变量的类型,var 表示变量名。
  • ++i、–i是左值,i++、i–是右值

3.2 左值引用和右值引用

  • 左值引用:
    • 左值引⽤就是对左值进⾏引⽤的类型,是对象的⼀个别名
    • 并不拥有所绑定对象的堆存,所以必须⽴即初始化。 对于左值引⽤,等号右边的值必须可以取地址,如果不能取地址,则会编译失败,或者可以使⽤const引⽤形式
  • 右值引用:
    • 右值引用所引用的对象是一个右值,右值对象是指其生命周期即将结束的对象,例如一次函数调用的返回值、临时变量等。
    • 表达式等号右边的值需要是右值,可以使⽤std::move函数强制把左值转换为右值

3.3 右值引用的使用场景

  • 以字符串类为例,假设有一个字符串对象 A,我们要把它赋值给另外一个字符串对象 B
string A = "HELLO";
string B = A;
  • 这样做的结果是,我们创建了两个相同内容但是不同地址的字符串对象,其中一个占用了额外的内存,存在性能问题。
  • 为了解决这个问题,C++11 移动语义提供了将对象 A 移动到 B 中的操作:
    • 当我们需要把一个对象赋值给另一个对象时,编译器会调用其复制构造函数或者赋值构造函数来创建一个新对象。但是,在某些情况下,复制操作会非常耗时;如果复制操作是不必要的,此时,使用移动构造函数,它不需要复制整个对象,而只是需要将原对象中的指针等资源转移到目标对象中即可,这样可以提高复制性能。
string A = "HELLO";
string B = std::move(A);
  • 上述代码就可以把对象 A 移动到 B 中,并不需要创建新的对象和分配内存。
  • 需要注意的是,只能对一个右值引用或者一个将要销毁的对象调用 std::move() 函数,否则会导致潜在的内存问题和错误。此外,在使用右值引用时,需要注意数据的生命周期问题,不要在使用后再次使用已经被移动的对象。

3.4 forward 完美转发

  • forward 完美转发实现了参数在传递过程中保持其值属性的功能,即若是左值,则传递之后仍然是左值,若是右值,则传递之后仍然是右值。
  • &&既可以对左值引用,亦可以对右值引用,但它后面的val值本身是个左值;&只能左值引用
template <class T>
void Print(T &t){ cout << "L" << t << endl; }
template <class T>
void Print(T &&t){ cout << "R" << t << endl; }template <class T>
void func(T &&t){Print(t);    Print(move(t));    Print(forward<T>(t));
}int main(){cout << "-- func(1) --" << endl;    func(1);  cout << "-- func(x) --" << endl;  int x = 10;    int y = 20;    func(x);  // x本身是左值    cout << "-- func(forward<int>(y)) --" << endl;    func(forward<int>(y)); //T为int,以右值方式转发y    cout << "-- func(forward<int&>(y)) --" << endl;    func(forward<int&>(y));    cout << "-- func(forward<int&&>(y)) --" << endl;    func(forward<int&&>(y));    return 0;
}

运行结果:在这里插入图片描述

3.5 emplace_back 减少内存拷贝和移动

  • emplace_back能就地通过参数构造对象,不需要拷贝或者移动内存,相比 push_back能更好地避免内存的拷贝与移动,使容器插入元素的性能得到进一步提升。在大多数情况下应该优先使用emplace_back来代替push_back。

4. lambda 匿名函数

  • 表示⼀个可调⽤的代码单元,没有命名的内联函数,不需要函数名因为我们直接(⼀次性的)⽤它,不需要其他地⽅调⽤它
  • 一般情况下,编译器可以自动推断出lambda表达式的返回类型,所以我们可以不指定返回类型。但是如果函数体内有多个return语句时,编译器无法自动推断出返回类型,此时必须指定返回类型。
  • 语法:[ 捕获列表 ] (参数列表) -> 返回类型 { 函数体 }
int main(){auto Add = [](int a, int b)->{ return a+b; };cout << Add(1, 2) << endl;return 0;
}

值捕获

void func() {     // c=10 d=20 add(1,2)=23int c = 10;int d = 20;auto add = [c, d](int a, int b) {cout << "c=" << c << endl;cout << "d=" << d << endl;return d+a+b;};d = 50;cout << "add(1, 2)=" << add(1, 2) << endl;
}

引用捕获

void func() {    // c=1 d=50 add(1,2)=53int c = 10;int d = 20;auto add = [&c, &d](int a, int b) {c = a;cout << "c=" << c << endl;cout << "d=" << d << endl;return d+a+b;};d = 50;cout << "add(1, 2)=" << add(1, 2) << endl;
}

隐式捕获、空捕获

void func() {int c = 10;int d = 20;// 如果[&]代表引用捕获,[=]代表值捕获,如果[]为空捕获表示Lambda不能使用所在函数中的变量auto add = [&](int a, int b) {  c = a; cout << "c=" << c << endl;cout << "d=" << d << endl;return d+a+b;};d = 50;cout << "add(1, 2)=" << add(1, 2) << endl;
}

表达式捕获

// c++14之后支持捕获右值,允许捕获的成员用任意的表达式进行初始化,被声明的捕获变量类型会根据 表达式进行判断,判断方式与使用 auto 本质上是相同的
void func4() {auto p = make_unqiue<int>(1);auto add = [v1=1, v2=move(p)](int x, int y)->int{ return x+y+v1+(*v2); };cout << "add(1, 2)=" << add(1, 2) << endl;
}

泛型捕获

void func() {auto add = [](auto x, auto y){ return x+y; };cout << "add(1, 2)=" << add(1, 2) << endl;cout << "add(1.1, 2.2)=" << add(1.1, 2.2) << endl;
}

可变

// 采用值捕获的方式,lambda不能修改其值,如果想要修改,使用mutable修饰;或者采用引用捕获的方式
void func() {int v = 5;auto ff = [v]() mutable { return ++v; };v = 0;auto j = ff(); // ff捕获的是值,即为5,因此j为6int m = 5;auto gg = [&m] {return ++m; };m = 0;auto n = gg(); // gg捕获的是引用,即为0,因此n为1
}

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

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

相关文章

c++计算路过人间的天数

这个是从edge提供的界面想起来的。感觉我们也可以写一个。 于是就动手写起来了。 难点有一个就是获取当前的日期。 其他的就是简单的计算了。 分为三部分&#xff1a; 1、出生的闰年判断和当年的闰年判断&#xff1b; 2、出生的那一年到年底有多少天&#xff0c;今年进行了…

浅谈C语言编译与链接

个人主页&#xff08;找往期文章包括但不限于本期文章中不懂的知识点&#xff09;&#xff1a;我要学编程(ಥ_ಥ)-CSDN博客 翻译环境和运行环境 在ANSI C&#xff08;标准 C&#xff09;的任何一种实现中&#xff0c;存在两个不同的环境。 第1种是翻译环境&#xff0c;在这个…

如何快速搭建一个ELK环境?

前言 ELK是Elasticsearch、Logstash和Kibana三个开源软件的统称&#xff0c;通常配合使用&#xff0c;并且都先后归于Elastic.co企业名下&#xff0c;故被简称为ELK协议栈。 Elasticsearch是一个实时的分布式搜索和分析引擎&#xff0c;它可以用于全文搜索、结构化搜索以及分…

C/C++语言学习路线: 嵌入式开发、底层软件、操作系统方向(持续更新)

初级&#xff1a;用好手上的锤子 1 【感性】认识 C 系编程语言开发调试过程 1.1 视频教程点到为止 1.2 炫技视频看看就行 1.3 编程游戏不玩也罢 有些游戏的主题任务就是编程&#xff0c;游戏和实际应用环境有一定差异&#xff08;工具、操作流程&#xff09;&#xff0c;在…

ROS2高效学习第十章 -- ros2 高级组件之 component 合并进程启动 其一

ros2 高级组件之 component 合并进程启动 1 前言和资料2 正文2.1 component 引入2.2 component_demo 3 总结 1 前言和资料 第十章我们将学习 ros2 的多个高级组件&#xff0c;包括 component&#xff0c;复杂 launch 文件&#xff0c;TF2&#xff0c;gazebo 和 rviz。本文我们…

鱼眼相机的测距流程及误差分析[像素坐标系到空间一点以及测距和误差分析]

由于最近在整理单目测距的内容&#xff0c;顺手也总结下鱼眼相机的测距流程和误差分析&#xff0c;如果有错误&#xff0c;还请不吝赐教。 参考链接: 鱼眼镜头的成像原理到畸变矫正&#xff08;完整版&#xff09; 相机模型总结&#xff08;针孔、鱼眼、全景&#xff09; 三维…

Linux安装redis(基于CentOS系统,Ubuntu也可参考)

前言&#xff1a;本文内容为实操记录&#xff0c;仅供参考&#xff01; 一、下载并解压Redis 1、执行下面的命令下载redis&#xff1a;wget https://download.redis.io/releases/redis-6.2.6.tar.gz 2、解压redis&#xff1a;tar xzf redis-6.2.6.tar.gz 3、移动redis目录&a…

深入了解高压电阻器的世界,探索其操作、类型和在各种高压应用中的关键作用

高压电阻器是高压条件下的专用元件&#xff0c;对于管理电压和散热至关重要 它们的工作原理是欧姆定律 类型包括线绕电阻、碳复合电阻、金属氧化物膜电阻、厚膜电阻和薄膜电阻这些电阻器在电力系统、医疗设备、汽车电子和电信设备中是必不可少的。 额定电压从600V到48KV 80p…

农村分散式生活污水分质处理及循环利用技术指南

标准已完成意见征集&#xff1a; 本文件给出了农村分散式生活污水分质处理及循环利用的总则、污水收集、污水分质处理、资源化利用、利用模式、运维管理等的指导。 本文件适用于农村分散式生活污水分质处理及循环利用的设施新建、扩建和改建工程的设计、施工与运维。 注:本文件…

Apache HBase(二)

目录 一、Apache HBase 1、HBase Shell操作 1.1、DDL创建修改表格 1、创建命名空间和表格 2、查看表格 3、修改表 4、删除表 1.2、DML写入读取数据 1、写入数据 2、读取数据 3、删除数据 2、大数据软件启动 一、Apache HBase 1、HBase Shell操作 先启动HBase。再…

学点Java_Day12_JDBC

1 JDBC 面向接口编程 在JDBC里面Java这个公司只是提供了一套接口Connection、Statement、ResultSet&#xff0c;每个数据库厂商实现了这套接口&#xff0c;例如MySql公司实现了&#xff1a;MySql驱动程序里面实现了这套接口&#xff0c;Java程序员只要调用实现了这些方法就可以…

C语言 C6031:返回值被忽略:“scanf“ 问题解决

我们在代码中 直接使用 scanf 就会出现这个错误 在最上面 加上 #define _CRT_SECURE_NO_WARNINGS//禁用安全函数警告 #pragma warning(disable:6031)//禁用 6031 的安全警告即可正常运行

Typora字数过多的时候造成卡顿现象如何解决?

Typora字数过多的时候造成卡顿现象如何解决&#xff1f; 点击 、切换、滚动、打字都有点卡顿&#xff0c;下面介绍三种方法&#xff0c;三种方法都可以尝试&#xff0c;建议先尝试方法一&#xff0c;效果不满意就用方法二&#xff0c;实在不行就最后一个取巧的办法。 方法1&a…

【大数据运维】minio 常见shell操作

文章目录 1. 安装2. 入门操作3. 命令帮助 1. 安装 下载 https://dl.min.io/client/mc/release/linux-amd64/ 赋权与使用 cp mc /usr/bin && chmod x /usr/bin/mc ./mc --help 2. 入门操作 # 添加minio到mc mc config host add minio_alias_name endpoint_adress …

R语言批量计算t检验,输出pvalue和均值

1.输入数据如下&#xff1a; 2.代码如下 setwd("E:/R/Rscripts/rG4相关绘图") # 读取CSV文件 data <- read.csv("box-cds-ABD-不同类型rg4-2.csv", stringsAsFactors FALSE)# 筛选出Type2列为指定五种类型的数据 filtered_data <- subset(data, …

电脑关机速度很慢怎么解决?

给电脑关机&#xff0c;总是要很久才完全关闭。这是因为计算机运行了太长时间&#xff0c;并且打开的程序太多&#xff0c;则关闭时间超过十秒钟&#xff0c;这是正常的现象。还有就是计算机升级或补丁程序更新也将导致计算机缓慢关闭。此时&#xff0c;建议耐心等待关闭完成。…

【C语言】预处理常见知识详解(宏详解)

文章目录 1、预定义符号2、define2.1 define 定义常量2.2 define 定义宏 3、#和##3.1 **#**3.2 **##** 4、条件编译&#xff08;开关&#xff09; 1、预定义符号 在C语言中内置了一些预定义符号&#xff0c;可以直接使用&#xff0c;这些符号实在预处理期间处理的&#xff0c;…

安卓国内ip代理app,畅游网络

随着移动互联网的普及和快速发展&#xff0c;安卓手机已经成为我们日常生活和工作中不可或缺的一部分。然而&#xff0c;由于地理位置、网络限制或其他因素&#xff0c;我们有时需要改变或隐藏自己的IP地址。这时&#xff0c;安卓国内IP代理App便成为了一个重要的工具。虎观代理…

局域网找不到共享电脑怎么办?

局域网找不到共享电脑是一种常见的问题&#xff0c;给我们的共享与合作带来一定的困扰。天联组网技术可以解决这个问题。本文将介绍天联组网的原理和优势&#xff0c;并探讨其在解决局域网找不到共享电脑问题中的应用。 天联组网的原理和优势 天联组网是一种基于加速服务器的远…

ES6 学习(三)-- es特性

文章目录 1. Symbol1.1 使用Symbol 作为对象属性名1.2 使用Symbol 作为常量 2. Iterator 迭代器2.1 for...of循环2.2 原生默认具备Interator 接口的对象2.3 给对象添加Iterator 迭代器2.4 ... 解构赋值 3. Set 结构3.1 初识 Set3.2 Set 实例属性和方法3.3 遍历3.4 相关面试题 4…