当前位置: 首页 > news >正文

【C++11(一)】列表初始化and右值引用

在这里插入图片描述

一、 统一的列表初始化

1.1 {}初始化

在C++98中,标准允许
使用花括号{}对数组或者结构体元素
进行统一的列表初始值设定

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

class Date
{
public:Date(int year, int month, int day):_year(year), _month(month), _day(day){cout << "Date(int year, int month, int day)" << endl;}
private:int _year;int _month;int _day;
};void test1()
{Date d1(2024, 1, 29); // old style// C++11支持的列表初始化,这里会调用构造函数初始化Date d2{ 2024, 1, 30 };Date d3 = { 2024, 1, 31 };vector<Date> vd1 = { d1, d2 };vector<Date> vd2 = { Date{ 2024, 1, 29 }, Date{ 2024, 1, 30 } };vector<Date> vd3 = { { 2024, 1, 29 }, { 2024, 1, 31 } };map<string, string> dict = { {"sort", "排序"}, {"string", "字符串"}, {"Date", "日期"} };pair<string, string> kv1 = { "Date", "日期" };pair<string, string> kv2{ "Date", "日期" };
}

1.2 std::initializer_list

std::initializer_list的介绍文档:
http://www.cplusplus.com/reference/initializer_list/initializer_list/
std::initializer_list是什么类型:

int main()
{// the type of il is an initializer_list auto il = { 10, 20, 30 };cout << typeid(il).name() << endl;initializer_list<int>::iterator it = il.begin();cout << it;// *it = 1; // 不能修改因为指向常量区return 0;
}

std::initializer_list使用场景:
std::initializer_list一般是作为构造函数的参数
C++11对STL中的不少容器就增加
std::initializer_list作为参数的构造函数
这样初始化容器对象就更方便了
也可以作为operator=的参数
这样就可以用大括号赋值

以前我们模拟实现的vector
不支持{}初始化和赋值
现在可以通过加一个构造函数实现
{}初始化和赋值

vector(initializer_list<T> il)
{// 第一种方法用迭代器支持/*typename initializer_list<T>::iterator it = il.begin();while (it != il.end()){push_back(*it);++it;}*/// 第二种方法范围for支持for (auto& e : il){push_back(e);}
}

二、声明

2.1 decltype

关键字decltype将变量的类型
声明为表达式指定的类型

// decltype的一些使用使用场景
template<class T1, class T2>
void F(T1 t1, T2 t2)
{
decltype(t1 * t2) ret;
cout << typeid(ret).name() << endl;
}
int main()
{
const int x = 1;
double y = 2.2;
decltype(x * y) ret; // x*y是double类型,ret的类型是double
decltype(&x) p;      // p的类型是const int*
cout << typeid(ret).name() << endl;
cout << typeid(p).name() << endl;
F(1, 'a');
return 0;
}// 以上都能通过auto解决,而下面则无法通过auto解决
// vector存储的类型跟x*y表达式返回值类型一致
vector<decltype(x * y)> v;

decltype可以推导一个表达式的类型
用这个类型实例化模板参数或定义对象

2.2 nullptr

由于C++中NULL被定义成字面量0
这样就可能回带来一些问题
因为0既能指针常量
又能表示整形常量
所以出于清晰和安全的角度考虑
C++11中新增了nullptr,用于表示空指针

三、STL中一些变化

3.1 新容器

用橘色圈起来是
C++11中的一些几个新容器
最有用的是unordered_map和
unordered_set
array和forward_list就比较鸡肋
在这里插入图片描述
基本每个容器都增加了一些C++11的方法

  1. 增加支持initializer_list的构造函数
    使用更方便, 有一定价值
  2. 增加cbegin和cend系列迭代器接口
    比较鸡肋
  3. 移动构造和移动赋值
    vector (vector&& x);
  4. 支持右值引用相关插入接口函数

3和4价值非常大, 提高了拷贝效率

四、右值引用和移动语义

4.1 左值引用

我们之前学的引用叫左值引用
而C++11中新增了的右值引用语法特性
无论左值引用还是右值引用
都是给对象取别名

左值是一个表示数据的表达式
(如变量名或解引用的指针)
通过获取它的地址+可以对它赋值
左值可以出现在赋值符号的左边,也可以是右边
定义时const修饰符后的左值
不能给他赋值,但是可以取它的地址
左值引用就是给左值的引用,给左值取别名

// 以下的p、b、c、*p都是左值
int* p = new int(0);
int b = 1;
const int c = 2;
// 以下几个是对上面左值的左值引用
int*& rp = p;
int& rb = b;
const int& rc = c;
int& pvalue = *p;

4.2 右值引用

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

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;

需要注意的是:
右值不能取地址的
但是给右值取别名后
会导致右值被存储到特定位置
且可以取到该位置的地址
也就是说例如:不能取字面量10的地址
但是rr1引用后,可以对rr1取地址,也可以修改rr1
如果不想rr1被修改,可以用const int&& rr1 去引用

double x = 1.1, y = 2.2;int&& rr1 = 10;const double&& rr2 = x + y;rr1 = 20;rr2 = 5.5;  // 报错

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

左值:

  1. 左值引用只能引用左值,不能引用右值
    (权限会被放大)
  2. 但是const左值引用既可引用左值
    也可引用右值
 // 左值引用只能引用左值,不能引用右值。int a = 10;int& ra1 = a;   // ra为a的别名//int& ra2 = 10;   // 编译失败,因为10是右值// const左值引用既可引用左值,也可引用右值。const int& ra3 = 10;const int& ra4 = a;

右值:

  1. 右值引用只能右值,不能引用左值
  2. 但是右值引用可以move以后的左值
// 右值引用只能右值,不能引用左值。int&& r1 = 10;// error C2440: “初始化”: 无法从“int”转换为“int &&”// message : 无法将左值绑定到右值引用int a = 10;int&& r2 = a;// 右值引用可以引用move以后的左值int&& r3 = std::move(a);

std::move的功能:
将一个左值强制转化为右值(将亡值)
(但并不能移动任何东西)
然后通过右值引用使用该值,以用于移动语义
从实现上讲
std::move基本等同于一个类型转换:
static_cast<T&&>(lvalue);
C++ 标准库使用比如vector::push_back等这类函数时
会对参数的对象进行复制,连数据也会复制
这会造成对象内存的额外创建
本来只是想把参数push_back进去就行了
通过std::move,可以避免不必要的拷贝操作
std::move是为性能而生
std::move是将对象的状态或者所有权
从一个对象转移到另一个对象
只是转移,没有内存的搬迁或者内存拷贝

4.4 右值引用使用场景和意义

右值分为纯右值和将亡值

// 模拟实现string
string s1("hello world");
// 如果s1是左值,调用正常拷贝构造走深拷贝
string ret1 = s1;// 如果是右值(将亡值)还走深拷贝就很不划算
// 将亡值是即将被delete的值
string ret2 = (s1+'!');

这时可以重新写一个拷贝构造
用右值引用来接收传参
以此区分左值和右值
如果是右值把我置空跟你交换一下
在这里插入图片描述
并且在函数传参上右值引用也能发挥作用

string to_string(int value)
{string ret;return ret; 
}int main()
{string s = to_string(123);return 0;
}

返回值把值赋给临时对象有一次拷贝构造
临时对象把值赋给s又会有一次拷贝构造
编译器优化之后把值直接赋给s
减少一次拷贝构造

有了右值引用
在这里插入图片描述
这样ret返回值不用调析构
s也不用调拷贝

总结:
左值引用减少拷贝, 提高效率
右值引用也是减少拷贝, 提高效率
但是他们的角度不同
左值引用是直接减少拷贝
右值引用是间接减少拷贝
识别出是左值还是右值
如果是右值, 则不再深拷贝
直接移动拷贝, 提高效率

五、模板中的&& 万能引用

模板中的&&不代表右值引用
而是万能引用,其既能接收左值又能接收右值
模板的万能引用只是提供了
能够接收同时接收左值引用和右值引用的能力

void Fun(int &x){ cout << "左值引用" << endl; }
void Fun(const int &x){ cout << "const 左值引用" << endl; }
void Fun(int &&x){ cout << "右值引用" << endl; }
void Fun(const int &&x){ cout << "const 右值引用" << endl; }template<typename T>
void PerfectForward(T&& t)
{Fun(t);
}
int main()
{PerfectForward(10);           // 右值int a;PerfectForward(a);            // 左值PerfectForward(std::move(a)); // 右值const int b = 8;PerfectForward(b);      // const 左值PerfectForward(std::move(b)); // const 右值

但是引用类型的唯一作用就是限制接收的类型
后续使用中都退化成了左值
如果希望在传递过程中保持它的
左值或者右值的属性
就需要用到完美转发

5.1 完美转发

std::forward 完美转发
在传参的过程中保留对象原生类型属性

template<typename T>
void PerfectForward(T&& t)
{Fun(std::forward<T>(t));
}
int main()
{PerfectForward(10);           // 右值int a;PerfectForward(a);            // 左值PerfectForward(std::move(a)); // 右值const int b = 8;PerfectForward(b);      // const 左值PerfectForward(std::move(b)); // const 右值

在这里插入图片描述
本篇博客完,感谢阅读🌹
如有错误之处可评论指出
博主会耐心听取每条意见

相关文章:

【C++11(一)】列表初始化and右值引用

一、 统一的列表初始化 1.1 &#xff5b;&#xff5d;初始化 在C98中&#xff0c;标准允许 使用花括号{}对数组或者结构体元素 进行统一的列表初始值设定 C11扩大了用大括号 括起的列表(初始化列表)的使用范围 使其可用于所有的内置类型和 用户自定义的类型 使用初始化列表时…...

为什么SSL会握手失败?SSL握手失败原因及解决方案

随着网络安全技术的发展&#xff0c;SSL证书作为网站数据安全的第一道防线&#xff0c;被越来越多的企业选择。SSL证书使用的是SSL协议&#xff0c;而SSL握手是SSL协议当中最重要的一部分。当部署SSL证书时&#xff0c;如果服务器和客户端之间无法建立安全连接&#xff0c;就会…...

STM32——智能小车

STM32——智能小车 硬件接线 B-1A – PB0 B-1B – PB1 A-1A – PB2 A-1B – PB10 其余接线参考51单片机小车项目。 1.让小车动起来 motor.c #include "motor.h" void goForward(void) {// 左轮HAL_GPIO_WritePin(GPIOB, GPIO_PIN_2, GPIO_PIN_SET);HAL_GPIO…...

开源:基于Vue3.3 + TS + Vant4 + Vite5 + Pinia + ViewPort适配..搭建的H5移动端开发模板

vue3.3-Mobile-template 基于Vue3.3 TS Vant4 Vite5 Pinia ViewPort适配 Sass Axios封装 vconsole调试工具&#xff0c;搭建的H5移动端开发模板&#xff0c;开箱即用的。 环境要求&#xff1a; Node:16.20.1 pnpm:8.14.0 必须装上安装pnpm&#xff0c;没装的看这篇…...

缩略图保持加密(thumbnail-preserving encryption, TPE)的理论基础

这涉及到一些视觉心理学等方面知识: 1、参考文献: 云存储图像缩略图保持的加密研究进展(中国图像图形学报) 一些视觉心理学的研究为TPE的成功实现提供了理论基础。Potter(1975, 1976)的研究表明人类的视觉系统能够在100 ms内从一个新场景中提取出相应的语义信息;250 ms内…...

nodejs+vue+mysql校园失物招领网站38tp1

本高校失物招领平台是为了提高用户查阅信息的效率和管理人员管理信息的工作效率&#xff0c;可以快速存储大量数据&#xff0c;还有信息检索功能&#xff0c;这大大的满足了用户和管理员这两者的需求。操作简单易懂&#xff0c;合理分析各个模块的功能&#xff0c;尽可能优化界…...

GEDepth:Ground Embedding for Monocular Depth Estimation

参考代码&#xff1a;gedepth 出发点与动机 相机的外参告诉了相机在世界坐标系下的位置信息&#xff0c;那么可以用这个外参构建一个地面基础深度作为先验&#xff0c;后续只需要在这个地面基础深度先验基础上添加offset就可以得到结果深度&#xff0c;这样可以极大简化深度估…...

校园圈子论坛系统--APP小程序H5,前后端源码交付,支持二开!uniAPP+PHP书写!

随着移动互联网的快速发展&#xff0c;校园社交成为了大学生们日常生活中重要的一部分。为了方便校园内学生的交流和互动&#xff0c;校园社交小程序逐渐走入人们的视野。本文将探讨校园社交小程序的开发以及其带来的益处。 校园社交小程序的开发涉及许多技术和设计方面。首先&…...

VMware vCenter告警:vSphere UI运行状况警报

vSphere UI运行状况警报 不会详细显示告警的具体内容&#xff0c;需要我们自己进一步确认告警原因。 vSphere UI运行状况警报是一种监控工具&#xff0c;用于检测vSphere环境中的潜在问题。当警报触发时&#xff0c;通常表示系统遇到了影响性能或可用性的问题。解决vSphere UI…...

C# 引用同一个dll不同版本的程序集

因为项目需要所以必须在项目中引用不同版本的同一程序集 我要引用的文件是newtonsoft.json.dll 两个版本为12.0.0.0 和4.0.0.0 1.如果已经先引入了newtonsoft.json 12.0.0.0版本的程序集&#xff0c;如果直接引入另一个版本的程序集的话会提示不成功&#xff0c;所以先将另一个…...

单机搭建hadoop环境(包括hdfs、yarn、hive)

单机可以搭建伪分布式hadoop环境&#xff0c;用来测试和开发使用&#xff0c;hadoop包括&#xff1a; hdfs服务器 yarn服务器&#xff0c;yarn的前提是hdfs服务器&#xff0c; 在前面两个的基础上&#xff0c;课可以搭建hive服务器&#xff0c;不过hive不属于hadoop的必须部…...

LEETCODE 170. 交易逆序对的总数

class Solution { public:int reversePairs(vector<int>& record) {if(record.size()<1)return 0;//归并 递归int left,right;left0;rightrecord.size()-1;int nummergeSort(left,right,record);return num;}int mergeSort(int left,int right, vector<int>…...

「HarmonyOS」EventHub事件通知详细使用方法

需求背景&#xff1a; 在开发过程中&#xff0c;肯定会出现触发特定事件&#xff0c;需要全局进行通知&#xff0c;与之相关的部分进行执行相应的修改方法。举个例子&#xff1a;修改了用户个人昵称&#xff0c;需要进行全局通知&#xff0c;在涉及昵称的部分收到通知后&#…...

为什么golang不支持可重入锁呢?

为什么golang不需要可重入锁&#xff1f; 在工程中使用锁的原因在于为了保护不变量&#xff0c;也可以用于保护内、外部的不变量。 基于此&#xff0c;Go 在互斥锁设计上会遵守这几个原则。如下&#xff1a; 在调用 mutex.Lock 方法时&#xff0c;要保证这些变量的不变性保持…...

聊一聊Tomcat的架构和运行流程,尽量通俗易懂一点

1、Tomcat的架构 这里可以看出 A、一个Tomcat就是一个Server&#xff0c;一个Server下会有多个Service&#xff0c; B、Service只负责封装多个Connector和一个Container&#xff08;Service本身不是容器&#xff0c;可以看做只是用来包装Connector和Container的壳&#xff0c…...

ModelArts加速识别,助力新零售电商业务功能的实现

前言 如果说为客户提供最好的商品是产品眼中零售的本质&#xff0c;那么用户的思维是什么呢&#xff1f; 在用户眼中&#xff0c;极致的服务体验与优质的商品同等重要。 企业想要满足上面两项服务&#xff0c;关键在于提升效率&#xff0c;也就是需要有更高效率的零售&#…...

Qt/C++音视频开发65-切换声卡/选择音频输出设备/播放到不同的声音设备/声卡下拉框

一、前言 近期收到一个用户需求&#xff0c;要求音视频组件能够切换声卡&#xff0c;首先要在vlc上实现&#xff0c;于是马不停蹄的研究起来&#xff0c;马上查阅对应vlc有没有自带的api接口&#xff0c;查看接口前&#xff0c;先打开vlc播放器&#xff0c;看下能不能切换&…...

MySQL原理(一)架构组成之逻辑模块(1)组成

总的来说&#xff0c;MySQL可以看成是二层架构&#xff0c;第一层我们通常叫做SQL Layer&#xff0c;在MySQL数据库系统处理底层数据之前的所有工作都是在这一层完成的&#xff0c;包括权限判断&#xff0c;sql解析&#xff0c;执行计划优化&#xff0c;query cache的处理等等&…...

一、cadence PDK 自学笔记-心法

我这边ADS /Cadence PDK基本大部分都是自学完成的。 当然也非常感谢我的前同事周**的帮忙&#xff0c;教了我很多基础的。另外也感谢我现在同事&#xff0c;李**和程*的帮忙&#xff0c;学习了很多cad的视角。 其实对于自学写PDK的小伙伴&#xff0c;一般都要如何学习呢&…...

防御保护--NAT策略

目录 NAT策略 NAT类型 server-map表 P2P --- peer to peer 网络类型 ​编辑 目标NAT--服务器映射 双向NAT ​编辑 多出口NAT NAT策略 静态NAT --- 一对一 动态NAT --- 多对多 NAPT --- 一对多的NAPT --- easy ip --- 多对多NAPT 服务器映射 源NAT--基于源IP地址进行转…...

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇&#xff0c;在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下&#xff1a; 【Note】&#xff1a;如果你已经完成安装等操作&#xff0c;可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作&#xff0c;重…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

【入坑系列】TiDB 强制索引在不同库下不生效问题

文章目录 背景SQL 优化情况线上SQL运行情况分析怀疑1:执行计划绑定问题?尝试:SHOW WARNINGS 查看警告探索 TiDB 的 USE_INDEX 写法Hint 不生效问题排查解决参考背景 项目中使用 TiDB 数据库,并对 SQL 进行优化了,添加了强制索引。 UAT 环境已经生效,但 PROD 环境强制索…...

centos 7 部署awstats 网站访问检测

一、基础环境准备&#xff08;两种安装方式都要做&#xff09; bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats&#xff0…...

基于uniapp+WebSocket实现聊天对话、消息监听、消息推送、聊天室等功能,多端兼容

基于 ​UniApp + WebSocket​实现多端兼容的实时通讯系统,涵盖WebSocket连接建立、消息收发机制、多端兼容性配置、消息实时监听等功能,适配​微信小程序、H5、Android、iOS等终端 目录 技术选型分析WebSocket协议优势UniApp跨平台特性WebSocket 基础实现连接管理消息收发连接…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

五年级数学知识边界总结思考-下册

目录 一、背景二、过程1.观察物体小学五年级下册“观察物体”知识点详解&#xff1a;由来、作用与意义**一、知识点核心内容****二、知识点的由来&#xff1a;从生活实践到数学抽象****三、知识的作用&#xff1a;解决实际问题的工具****四、学习的意义&#xff1a;培养核心素养…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令&#xff0c;在Linux上安装软件&#xff0c;以及如何在Linux上部署一个单体项目&#xff0c;大多数同学都会有相同的感受&#xff0c;那就是麻烦。 核心体现在三点&#xff1a; 命令太多了&#xff0c;记不住 软件安装包名字复杂&…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...