【C++】C++11

文章目录

  • C++11
    • 1. 统一的列表初始化
      • 1.1 {}初始化
    • 2. 声明
      • 2.1 auto
      • 2.2 decltype
      • 2.3 nullptr
    • 3. 右值引用和移动语义
      • 3.1 左值引用和右值引用
      • 3.2 左值引用与右值引用比较
      • 3.3 右值引用使用的场景和意义
      • 3.4 完美转发
    • 4. 可变参数模板
    • 5. lambda表达式
      • 5.1 函数对象与lambda表达式
    • 6. 线程库
      • 6.1 thread类的简单介绍
      • 6.2 线程函数参数
    • 7. 包装器
    • 8.bind

C++11

1. 统一的列表初始化

1.1 {}初始化

C++11扩大了用大括号括起来的列表的使用范围。使其适用于所有的内置类型和用户自定义的类型。使用初始化列表时,可以添加等号(=),也可以不添加

2. 声明

2.1 auto

C++11当中将其用于实现自动类型推断,这样要求必须进行显示初始化,让编译器将定义对象的类型设置为初始化值的类型。

2.2 decltype

将变量的类型声明为表达式指定的类型

2.3 nullptr

#ifndef NULL
#ifdef __cplusplus
#define NULL   0
#else
#define NULL   ((void *)0)
#endif
#endif

3. 右值引用和移动语义

3.1 左值引用和右值引用

传统的C++语法当中就有引用的概念,C++11当中增加了右值引用语法特性。无论是左值引用还是右值引用都是给变量起别名

什么是左值?什么是右值?

左值表示一个数据的表达式(如变量名或者解引用的指针),我们可以获取它的地址+可以对它赋值。左值可以出现在赋值符号的左边,右值不能出现在赋值符号的左边

int main() {// 以下都是左值int* p = new int(0);int b = 1;const int c = 2;// 一下都是左值的引用int*& rp = p;int& rb = b;const int& rc = c;int& value = *p;return 0;
}

什么是右值?什么是右值引用?

右值也是一个数据的表达式。如: 字面常量、表达式返回值、函数返回值(这个不能是左值引用返回)。右值不能出现在赋值符号的左边,右值不能取地址。右值引用就是对右值的引用,给右值起别名。


int main()
{double x = 1.1, y = 2.2;
// 以下几个都是常见的右值10;x + y;fmin(x, y);
// 以下几个都是对右值的右值引用int&& rr1 = 10;double&& rr2 = x + y;double&& rr3 = fmin(x, y);
// 这里编译会报错:error C2106: “=”: 左操作数必须为左值10 = 1;x + y = 1;fmin(x, y) = 1;return 0;
}

需要注意的是右值是不能取地址的,但是给右值取别名之后,会导致右值存储到特别的位置,并且可以取到该位置的地址。

int main() {double x = 1.1, y = 2.2;int&& rr1 = 10;const double&& rr2 = x + y;rr1 = 20;rr2 = 5.5; // 报错return 0;
}

3.2 左值引用与右值引用比较

左值引用总结:

  1. 左值引用只能引用左值,不能引用右值
  2. const左值引用既可以引用左值,也可以引用右值

右值引用总结:

  1. 右值引用只能引用右值,不能引用左值
  2. 右值引用可以引用move以后的左值

3.3 右值引用使用的场景和意义

左值引用的短板:

image-20230709205301133

只能使用传值返回,传值返回会导致至少一次拷贝构造

移动构造本质是将参数右值的资源窃取过来,占为已有。那么就不用做深拷贝了,所以叫做移动构造。就是窃取别人的资源来构造自己

不仅仅有移动构造,还有移动赋值

qsnpfu5bti-1688907511110.png

3.4 完美转发

模板当中的&& 不代表右值引用。而是万能引用。既能接收左值又能接收右值。模板的万能引用只是提供了同时接收左值引用又能接收右值引用。但是引用类型的唯一作用就是限制了接收的类型,后续引用中都退化成为了左值。如果在传递的过程当中保持左值或右值的属性,就需要这个完美转发了

forward保证了传参过程中的原生类型属性

强制生成默认函数的关键字default

比如我们提供了拷贝构造,就不会生成移动构造了,我们可以使用default关键字显示指定移动构造生成

禁止生成默认构造函数的关键字delete

4. 可变参数模板

template<class...Args>
void show(Args...args) {}

递归方式展开参数包:

// 递归终止函数
template <class T>
void ShowList(const T& t)
{cout << t << endl;
}
// 展开函数
template <class T, class ...Args>
void ShowList(T value, Args... args)
{cout << value <<" ";ShowList(args...);
}
int main()
{ShowList(1);ShowList(1, 'A');ShowList(1, 'A', std::string("sort"));return 0;
}

5. lambda表达式

lambda表达式实际上是一个匿名函数

lambda表达式的书写格式:

[capture-list] (parameters) mutable->return-type{statement}

int main() {int a = 3, b = 4;[=]{return a + b;};auto fun1 = [&](int c){b = a + c;};fun1(10);cout << b << " " << a << endl;// 复制捕捉xint x = 20;auto add_x = [x](int a) mutable {x *= 2;return a + x;};cout << add_x(10) << endl;cout << typeid(a).name() << endl;cout << typeid(add_x(10)).name() << endl;
}
  • [var]表示值传递方式,捕捉变量var
  • [=]:表示值传递方式,捕捉所有父作用域中的变量
  • [&var]:表示引用传递捕捉变量var
  • [&] : 表示引用传递所有父作用域中的变量
  • [this]:表示值传递方式捕捉当前的this指针

image-20230709213816350

5.1 函数对象与lambda表达式

函数对象又称为仿函数,是可以像函数一样使用的对象。就是在类中重载了operator()运算符的类对象

al3cwq0fkd-1688910086295.png

6. 线程库

6.1 thread类的简单介绍

在C++11之前,涉及到多线程的问题,都是和平台相关的。window和Linux都有自己的接口,这就让代码的移植性比较差。C++11当中最重要的特性就是对线程进行了支持,使C++在编程时不需要依赖第三方库

注意:

  1. 线程是操作系统中的概念,线程对象可以关联一个线程,用来控制线程以及获取线程的状态

  2. 当创建一个线程时, 没有提供线程函数,该对象实际没有对应任何线程

  3. 当创建一个线程对象后,并且线程关联线程函数,这个线程就被启动。与主线程一起运行。线程函数一般按照如下三种方式提供:

    1. 函数指针
    2. lambda表达式
    3. 函数对象

6.2 线程函数参数

线程函数参数是以值拷贝的方式拷贝到线程栈空间当中。因此即使线程参数为引用类型,在线程当中修改之后也还是不能修改外部实参。因为实际引用的是线程栈中的拷贝,不是外部实参

两个线程交替打印奇书偶数

#include "iostream"
#include "condition_variable"
#include "mutex"
#include "thread"using namespace std;//支持两个线程交替打印,t1打印奇数,t2一个打印偶数
int main(){mutex mtx;condition_variable cv;int n = 100;int x = 1;// 问题1:如何保证t1先运行,t2阻塞?// 问题2:如何防止一个线程不断运行?thread t1([&, n]() {while (true){unique_lock<mutex> lock(mtx);if (x >= 100)break;if (x % 2 == 0) // 偶数就阻塞{cv.wait(lock);}
//			cv.wait(lock, [&x]() {return x % 2 != 0; });cout << this_thread::get_id() << ":" << x << endl;++x;cv.notify_one();}});thread t2([&, n]() {while (true){unique_lock<mutex> lock(mtx);if (x > 100)break;if (x % 2 != 0) // 奇数就阻塞{cv.wait(lock);}
//			cv.wait(lock, [&x](){return x % 2 == 0; });cout << this_thread::get_id() << ":" << x << endl;++x;cv.notify_one();}});t1.join();t2.join();return 0;
}

7. 包装器

function包装器也叫适配器,我们来看看为什么需要包装器?本质上是一个类模板,也是一个包装器。

包装器的一个使用例子:

使用包装器之前的:

class Solution {
public:static int evalRPN(vector <string> &tokes){stack<int> s;for (auto&str : tokes){if (str == "+" || str == "-" || str == "*" || str == "/"){int right = s.top();s.pop();int left = s.top();s.pop();switch(str[0]){case '+':s.push(left + right);break;case '-':s.push(left - right);break;case '*':s.push(left * right);break;case '/':s.push(left / right);break;default:break;}}else{s.push(stoi(str));}}}
};

使用包装器之后:

class Solution {
public:static int evalRPN(vector <string> &tokes){stack<int> st;map<string, function<int(int, int)>> opFuncMap ={{"+", [](int i, int j){return i + j;}},{"-", [](int i, int j){return i - j;}},{"*", [](int i, int j){return i * j;}},{"/", [](int i, int j){return i / j;}}};for (auto& str : tokes){if (opFuncMap.find(str) != opFuncMap.end()){int right = st.top();st.pop();int left = st.top();st.pop();st.push(opFuncMap[str](left, right));}}}
};

8.bind

bind函数定义在头文件当中,是一个函数模板,它就像一个函数包装器(适配器)接收一个可调用对象生成一个新的可调用对象来“适应”原对象的参数列表。

一般而言,我么可以原本接收N个函数的参数的函数fn,通过绑定一些参数,返回一个接收M个参数(M可以大于N)

调用bind的一般形式是:auto newCallable = bind(callable, arg_list)

//表示绑定函数plus 参数分别由调用 func1 的第一,二个参数指定
std::function<int(int, int)> func1 = std::bind(Plus, placeholders::_1,placeholders::_2);

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

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

相关文章

STM32入门之创建工程模板

1.STM32固件库的结构图如下。从图中可以看出&#xff0c;我们在配置STM32的固件库时需要配置用户层、CMSIS层的文件。配置库文件即正确的配置这些函数的文件。CMSIS(Cortex Microcontroller Software Interface Standard)是ARM公司提供的微控制器软件接口标准&#xff0c;所有使…

macos M1安装多个版本jdk

1、安装jdk 8 到 oracle 官网 https://www.oracle.com/java/technologies/javase/javase8u211-later-archive-downloads.html 找到 macOS x64 DMG Installer 后面的下载链接下载安装包 java的jdk 都安装在以下目录 ls /Library/Java/JavaVirtualMachines/jdk-1.8.jdk jdk-1…

Data Structure, Algorithm,and Applications in C++

在学习这本书进阶内容之前&#xff0c;我们可以跟着它的第一章部分再巩固和复习。本书由Sartaj Sahni撰写&#xff0c;由王立柱和刘志红翻译。全书通俗易懂&#xff0c;内容丰富&#xff0c;是巩固C内容的不二选择。希望本文对各位有所帮助。 目录 1.函数与参数 1.1.传值参数…

C++初探

目录 经典开头 — C的历史 作用域运算符 using的用法 命名空间 - namespace 命名空间的基本使用 特殊的命名空间 - 无名命名空间 全部展开和部分展开 std — C所有的标准库都在std命名空间内 省缺值 - 默认参数 占位参数 内联函数 - inline 函数重载 函数重载的用…

【Unity2D】相机移动以及设置相机边界

添加相机 添加相机时&#xff0c;首先需要在unity中添加 Cinemachine 包 第一次使用这个包时&#xff0c;需要在Package Manager中搜索并安装 安装Camera Mechine包后&#xff0c;添加2D Camera 设置跟随对象为Ruby &#xff08;从Hierarchy中将Ruby拖动到Follow中&#xff0…

kafka 2.1.1 java的消费者客户端如何获取数据源码

KafkaConsumer 一、kakfa消费者暴露给业务系统获取数据的方法1 首先从缓冲区队列取数&#xff0c;没有数据则请求服务端来获取数据1.1循环从队列中取数&#xff0c;给到空或者已被提取的nextInLineRecords(1)当nextInLineRecords的数据被提取时&#xff0c;就把nextInLineRecor…

c函数学习

函数的概念 函数是c语言的功能单位&#xff0c;实现一个功能可以封装一个函数来实现。定义函数的时候一切以功能为目的&#xff0c;根据功能去定义函数的参数和返回值 函数的分类 从定义角度分类&#xff1a;库函数&#xff08;c库实现的&#xff09;&#xff0c;自定义函数&…

一、大数据技术之Flume(简介)

第1章 Flume概述 1.1 Flume定义 Flume是Cloudera提供的一个高可用的&#xff0c;高可靠的&#xff0c;分布式的海量日志采集、聚合和传输的系统。Flume基于流式架构&#xff0c;灵活简单。 1.2 Flume基础架构 Flume组成架构如下图所示。 1.2.1 Agent Agent是一个JVM进程&…

微信小程序23__flex布局 相关的3种居中: 水平居中_垂直居中_水平垂直居中

3 种居中方式&#xff0c; 在页面布局中经常用到&#xff0c; 现作一记录。 第一种 水平居中 类似这样写法 display: flex; flex-direction: column; //垂直布局 align-items: center; // 水平居中 justify-content: space-a…

NLP实战8:图解 Transformer笔记

目录 1.Transformer宏观结构 2.Transformer结构细节 2.1输入 2.2编码部分 2.3解码部分 2.4多头注意力机制 2.5线性层和softmax 2.6 损失函数 3.参考代码 &#x1f368; 本文为[&#x1f517;365天深度学习训练营]内部限免文章&#xff08;版权归 *K同学啊* 所有&#…

vue 路由守卫

全局路由守卫 beforeEach 路由跳转前触发to 代表 到那个页面去from 代表从哪个页面来next 表示放行 beforeResolve 表示 组件解析后触发的钩子 afterEach 表示路由跳转完成之后i触发的钩子 全局路由钩子执行顺序 beforeEach > beforeResolve>afterEach 局部路由…

在外远程NAS群晖Drive - 群晖Drive挂载电脑磁盘同步备份【无需公网IP】

文章目录 前言1.群晖Synology Drive套件的安装1.1 安装Synology Drive套件1.2 设置Synology Drive套件1.3 局域网内电脑测试和使用 2.使用cpolar远程访问内网Synology Drive2.1 Cpolar云端设置2.2 Cpolar本地设置2.3 测试和使用 3. 结语 前言 群晖作为专业的数据存储中心&…

【Hadoop 01】简介

目录 1 Hadoop 简介 2 下载并配置Hadoop 2.1 修改/etc/profile 2.2 修改hadoop-env.sh 2.3 修改core-site.xml 2.4 修改hdfs-site.xml 2.5 修改mapred-site.xml 2.6 修改yarn-site.xml 2.7 修改workers 2.8 修改start-dfs.sh、stop-dfs.sh 2.9 修改start-yarn.sh、s…

Elemui表单合并

原代码形式 <template><el-table:data"tableData"borderstyle"width: 100%"><el-table-columnprop"date"label"日期"width"180"></el-table-column><el-table-columnprop"name"label…

TC3XX - MCAL知识点(十):ICU EB-tresos配置说明与代码浅析

目录 1、概述 2、EB-tresos配置 2.1、实验目标 2.2、MCU配置 2.2.1、McuGtmTimAllocationConf 2.2.2、GtmClusterConf 2.2.3、McuClockSettingConfig 2.3、ICU配置 2.3.1、IcuOptionalApis

leetcode 399. 除法求值

给你一个变量对数组 equations 和一个实数值数组 values 作为已知条件&#xff0c;其中 equations[i] [Ai, Bi] 和 values[i] 共同表示等式 Ai / Bi values[i] 。每个 Ai 或 Bi 是一个表示单个变量的字符串。 另有一些以数组 queries 表示的问题&#xff0c;其中 queries[j]…

Java: 转换流

转换流 1.定义 是字符流和字节流之间的桥梁。 分为&#xff1a; 字符转换输入流&#xff08;InputStreamReader&#xff09;字符转换输出流&#xff08;OutputStreamWrite&#xff09; 2.作用 1.作用1:指定字符集读写 在jdk11时&#xff0c;这种方式被淘汰了。 案例1&…

.NET各版本支持的操作系统

借助虚拟机和测试机&#xff0c;检测各版本操作系统对.NET的支持情况。 安装操作系统后&#xff0c;实测安装相应运行时并能够运行星尘代理为通过。 测试平台&#xff1a;VMware Workstation 镜像来源&#xff1a;MSDN I Tell You 参考&#xff1a; .NET Framework 版本和…

WebGL 概念和基础入门

WebGL 概念和基础入门 WebGL 是什么 对于 WebGL 百度百科给出的解释是 WebGL 是一种 3D 绘图协议&#xff0c;而对此维基百科给出的解释却是一种 JavaScript API。由于 WebGL 技术旨在帮助我们在不使用插件的情况下在任何兼容的网页浏览器中开发交互式 2D 和 3D 网页效果&…

使用redis RedisAtomicLong 生成订单号

背景 产品需求要生成有序的订单 key 年月日时分秒 6位序号 由00001-99999组成 且每天都是从00001开始 公司系统有部署多台服务&#xff0c;这需要一个有序的序列不能重复而且得保证获取时的原子性这里 我们考虑使用了redis Incr 这个命令 Redis Incr 命令能将 key 中储存的数…