当前位置:首页 » 《休闲阅读》 » 正文

【C++】C++11(统一列表初始化、声明、右值引用)

5 人参与  2024年12月24日 16:01  分类 : 《休闲阅读》  评论

点击全文阅读


  ?个人主页:秦jh_-CSDN博客
? 系列专栏:https://blog.csdn.net/qinjh_/category_12575764.html?spm=1001.2014.3001.5482

 9efbcbc3d25747719da38c01b3fa9b4f.gif​ 

目录

C++11简介

统一的列表初始化 

{}初始化 

std::initializer_list

声明 

auto 

decltype

nullptr

STL中一些变化 

右值引用和移动语义 

左值引用和右值引用  

 左值引用与右值引用比较

 右值引用使用场景和意义

 右值引用的属性​编辑

 右值引用引用左值及其一些更深入的使用场景分析

STL容器插入接口函数也增加了右值引用版本: 

 完美转发

模板中的&& 万能引用 

 std::forward 完美转发


前言

    ? hello! 各位铁子们大家好哇。

             今日更新了C++11的相关内容
    ? 欢迎大家关注?点赞?收藏⭐️留言?

C++11简介

相比于 C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中 约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。相比较而言, C++11能更好地用于系统开发和库开发、语法更加泛华和简单化、更加稳定和安全,不仅功能更 强大,而且能提升程序员的开发效率,公司实际项目开发中也用得比较多。

统一的列表初始化 

{}初始化 

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

struct Point{ int _x; int _y;};int main(){ int array1[] = { 1, 2, 3, 4, 5 }; int array2[5] = { 0 }; Point p = { 1, 2 }; return 0;}

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

 

 当没有写构造函数时,无法用{}初始化自定义类型。写出构造函数后就可以,这是C++11的语法特性。本质上是通过{}构造一个A对象,然后通过拷贝构造给aa1。但是编译器会优化,连续的构造和拷贝构造会被优化为直接构造。

实际上C++98就支持了单参数的构造函数的隐式类型转换,C++11支持了多参数的。 

如果不想让隐式类型转换发生,可以在构造函数前加上explicit。 

 

单参数构造时,也可使用{},并且{}可要可不要。 甚至连内置类型也可用列表初始化。

std::initializer_list

如果使用{}初始化,像vector这种容器,我们无法知道每次初始化的参数个数是几个, 所以C++11对STL中的不少容器就增加 std::initializer_list作为参数的构造函数。

initializer_list也支持迭代器遍历。

v5是构造,v3是由 initializer_list隐式类型转换成一个vector,然后再拷贝给v3得到的。

声明 

auto 

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

由上图可知,x不是i的引用。j和i的地址相同,但y和i的地址不同。如果想要y的地址与i相同,就得用auto&

decltype

typeid 可以拿到这个类型的字符串。

如果我们想用推出来的类型定义对象,不能用typeid。得用decltype。 

nullptr

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

STL中一些变化 

红色框中是C++11新增的容器,实际有用的是unordered_set和unordered_map。array就是静态的数组,只不过检查数组越界更严格,实际没什么用。forward_list就是一个单向链表,实际也没什么用。

右值引用和移动语义 

左值引用和右值引用  

无论左值引用还是右值引用,都是给对象取别名。 

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

 

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

 左值引用与右值引用比较

 左值引用总结:

左值引用只能引用左值,不能引用右值。但是const左值引用既可引用左值,也可引用右值。

右值引用总结: 

右值引用只能右值,不能引用左值。但是右值引用可以引用move以后的左值。 

 右值引用使用场景和意义

下面的测试用VS2019,VS2022优化更大,测试结果会不同。

func1中左值引用可以减少拷贝。func2中,返回值是左值引用时也可以,但如果返回值是func2中的局部对象时,出了作用域就销毁了,所以无法用左值引用返回。 

 

比如上方的to_string,str是局部对象,出了作用域就销毁了,就不能用左值引用返回。右值引用返回也是同理。

局部对象出作用域就会销毁,所以会拷贝构造一个临时对象,然后再拷贝构造给ret1。不过vs2022编译器会优化,连续的构造、拷贝构造会优化为直接构造。 

如果把上面那句话拆成两句,编译器就无法优化。先构造ret1,然后构造str,接着拷贝构造临时对象,最后进行赋值拷贝。 

 右值还可以分为纯右值(内置类型)和将亡值(自定义类型)。

STL中增加了移动构造解决上述问题:

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

// 拷贝构造// 左值string(const string& s):_str(nullptr){cout << "string(const string& s) -- 深拷贝" << endl;_str = new char[s._capacity + 1];strcpy(_str, s._str);_size = s._size;_capacity = s._capacity;}// 移动构造// 右值(将亡值)string(string&& s):_str(nullptr){cout << "string(string&& s) -- 移动构造" << endl;swap(s);}

没有移动构造时,传左值和右值都会调用拷贝构造。有了移动构造,如果传的是右值,会优先调用移动构造。

 有了移动构造后

str是左值,要拷贝构造一个临时对象,有了移动构造,就调用移动构造给ret1。但是编译器还会继续优化,编译器将str强制识别为右值,使其调用移动构造,两次连续的移动构造又会被继续优化为一次移动构造。 

因为s3不是已存在的对象,所以编译器会优化。所以把s1强转成右值时,就会调用移动构造,交换s3和s1的资源。 

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

//移动赋值//s3 = 将亡值string& operator=(string&& s){cout << "string(string&& s) -- 移动赋值" << endl;swap(s);return *this;}

因为如果是用一个已经存在的对象接收,编译器就没办法优化了。 所以调用了移动构造和移动赋值。

 右值引用的属性

右值引用的属性是左值。如上图,右值引用s被当作swap函数的左值引用的形参。 

 右值引用引用左值及其一些更深入的使用场景分析

当需要用右值引用引用一个左值时,可以通过move 函数将左值转化为右值。C++11中,std::move()函数位于 头文件中,该函数名字具有迷惑性, 它并不搬移任何东西,唯一的功能就是将一个左值强制转化为右值引用。

这里我们把s1 move处理以后, 会被当成右值,调用移动构造 

STL容器插入接口函数也增加了右值引用版本: 

 

 push_back里面要new一个节点,所以会有拷贝构造。因为s1是左值,所以会调用拷贝构造。第二个push_back里是右值,就可以调用移动构造。

int类型,日期类等浅拷贝类型,没有移动系列函数。因为他们不需要拷贝构造和移动构造。浅拷贝的类不存在转移资源的说法。 

 完美转发

模板中的&& 万能引用 

 模板中的&&不代表右值引用,而是万能引用,其既能接收左值又能接收右值。因为右值引用的属性是左值,所以上面Fun(t)里的t都是左值,因此会产生这个结果。如果希望能够在传递过程中保持它的左值或者右值的属性,需要用到完美转发。

 std::forward 完美转发

 完美转发保持了t的原生属性类型,即如果传的是左值,就不变。传的是右值,就推成右值引用。


点击全文阅读


本文链接:http://m.zhangshiyu.com/post/206241.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

最新文章

  • 林语熙周晏京(离婚后,老公天天跪求复合全集阅读)最新章节免费在线阅读_《离婚后,老公天天跪求复合全集阅读》最新热门小说 -
  • 顾绫雪嬴政《被始皇读心后,文武百官卷疯了!完结版阅读》完整版免费在线阅读_(顾绫雪嬴政)全集免费阅读 -
  • 情深意长皆成空完整版阅读(沈卿林砚辞)抖音热文_《情深意长皆成空完整版阅读》最新章节免费在线阅读 -
  • 姐姐为暴富重伤傅家金孙后火葬场了全集阅读小说(傅延江瑶)全文免费阅读无弹窗大结局_(姐姐为暴富重伤傅家金孙后火葬场了全集阅读免费阅读全文大结局)最新章节列表_笔趣阁(姐姐为暴富重伤傅家金孙后火葬场了全集阅读) -
  • 乔以诺萧瑾淮(不是你好是我好全集阅读)精彩试读_《不是你好是我好全集阅读》全本阅读 -
  • 白月光双双《重生后我成全老公和白月光,他却急了全集》全文免费阅读无弹窗大结局_(白月光双双)最新章节免费在线阅读 -
  • 苏小枫苏末小说免费笔趣阁_苏小枫苏末小说全章完本大结局
  • 死遁后他疯了最新小说全文阅读_最新免费小说沈轻洲林梦江之雪_完本小说(死遁后他疯了)
  • 免费小说《顾里宋婷婷小岳欧颖倩》已完结(顾里宋婷婷小岳欧颖倩)热门小说大结局全文阅读笔趣阁
  • 侄子为求富贵,变性后全家后悔最新小说_免费小说全文阅读(苏小枫苏末)_侄子为求富贵,变性后全家后悔苏小枫苏末小说推荐完结
  • 最新《沈轻洲林梦江之雪》小说(全集完整新上小说大结局(沈轻洲林梦江之雪))全文阅读笔趣阁
  • 拒绝嫁给姐夫后,我在八零年代暴富了(陈小棠沈正韩)阅读 -

    关于我们 | 我要投稿 | 免责申明

    Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1