| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 呕心沥血梳理C++新标准超好用的新特性(实战必备) -> 正文阅读 |
|
[C++知识库]呕心沥血梳理C++新标准超好用的新特性(实战必备) |
目录 C++标准更新迭代非常快,我们熟悉的标准有C++98,C++11,C++14,其实最新的标准已经到C++20了但是支持该标准的IDE还很少。其实对于很多人来说,能掌握到C++14已经非常不错了。但是事实上是很多人对C++的掌握还停留在C++98上,连11的很多新特性都没有用到。C++新标准引入的新特性能提高编程的效率和代码的鲁棒性,学习一下对程序员的编程实战大有裨益,这里我结合一下自己的学习笔记和理解,总结了一下,希望对大家有所帮助。 这里提一句,之前在极客时间上学习了罗剑锋老师的C++实战笔记,感觉非常不错,收获也挺大的,建议感兴趣的可以去学习一下。 闲话少说,开始正文。 1.C++属性C++的属性,主要用来控制程序的编译指令的, 针对C++属性标准并没有引入新的关键字,而是用两对中括号的形式来进行表示[[*****]],方括号中间可以添加对应的属性标签。 C++11中只定义了noreturn和carries_dependency两个属性标签,用处并不大。 C++14中定义了deprecated用来标记不推荐使用的函数或者类,使用该标签代表着这个函数或者类被废弃了。 使用方法如下:
如何在调用该函数的地方在编译的时候都会弹出下面的警告信息
在发布对外的库的时候,如果要提示用户接口或者类即将废弃,可以使用该属性标签,同时在我们编码的过程中如果要升级一个或者废弃一个接口也可以使用该属性标签。C++17和C++20又增加了五六个属性,比如fallthrough、likely等等。 现在的VS2015对C++14的支持还挺全面的,如果你的IDE是VS2015该特性可以放心使用 2.静态断言(static_assert)静态断言和普通断言的区别就是,静态断言在编译的过程中生效,普通断言在运行过程中生效。静态断言可以用来在编译构造过程中进行断言检查。
3.final、default、delete关键字的使用在继承关系中通过C++11的关键字final阻断继承关系,显式的禁用继承,防止其他人有意或者无意的产生派生类。
C++类里面,原先有四大函数,分别为:构造函数、析构函数、拷贝构造函数、拷贝赋值函数。C++11因为引入了右值和转移,又多出了两大函数:转移构造函数和转移赋值函数。 对于比较重要的构造函数和析构函数,如果不想自己写, 应该使用“=default”,明确指明,应该实现这个函数,但采用默认的形式。
C++11还引入了“=delete”的形式,明确指明禁用某个函数形式,不仅限于构造/析构,还可以用于任何函数(成员函数\自由函数)。
4.成员变量初始化在C++11中可以在成员变量声明的时候对其进行初始化。
5.类型别名C++11扩展了关键字using的用法,增加了typedef的能力,可以定义类型的别名,它的格式与typedef正好相反,别名在左,原名称在右边。
6.委托构造函数在C++11中,可以使用委托构造函数新特性,一个构造函数直接调用另外一个构造函数。这样我们可以对构造函数进行封装,对外暴露出统一的构造函数。
7.const、volatile、mutable关键字1.const const是一个类型修饰符,可以给任何对象附加上“只读”属性,保证安全。它可以用来修饰引用和指针,const& 可以引用任何类型,是函数入口参数的最佳类型。它还可以修饰成员函数,表示函数“只读”的,const 对象只能调用const成员函数 2.volatile 它表示变量可能被“不被察觉”的修改,禁止编译器优化,影响性能,应当少用 3.mutable 它用来修饰成员变量,允许const成员函数修改,mutable变量的变化不影响对象的常量性,但要小心不要误用损坏对象。 C++11里面mutable多了一种用法,可以修复师lambda表达式。 C++11引入了新关键字constexpr,能够表示真正的编译阶段常量,甚至能够编写在编译阶段运行的数值函数。 8.防止头文件重复引入VS编译器支持指令#pragma once ,也可以实现“#Include Guard”,但它不是标准的,不能跨平台,不推荐使用。在引入头文件的时候,为了防止头文件重复引用,通过宏定义来实现。
虽然这种手法比较原始,但目前来说是唯一有效的方法,而且向下兼容C语言,建议强制使用。 9.auto/decltype自动类型推导auto避免了对类型的“硬编码”,也就是说类型不是写死的,而是自动推导出来的。但是auto有固定的使用场景要注意。 1.auto的自动推导能力,只能用于“初始化”的场合。包括赋值初始化和花括号初始化,变量右边必须有一个表达式。如果只是变量声明是无法使用auto的。在类成员变量初始化的时候,目前C++不支持推导类型。 2.auto总是推导出的“值类型”,绝对不是“引用类型” 3.auto可以附加上const、volatile、*、&这样的类型修饰符,得到新的类型。
auto自动类型推导,要求必须要从表达式推导。而decltype的形式很像函数,后面的圆括号里添加用于计算类型的表达式,其它的和auto一样,也能加上const、*、&等修饰符。因为decltype自带表达式可以直接用来进行变量声明。
auto和decltype的区别:decltype不仅能够推导出值类型,而且还能推导出引用类型,也就是表达式的原始类型。decltype可以直接从一个引用类型的变量推导出引用类型,而auto就会把引用去掉,推导出值类型。 可以把decltype看成是一个真正的类型名称,用在变量声明、函数返回值/参数、模板参数等任何类型出现的地方。
虽然decltype类型推导更加精准,但是表达式要书写两次,左边类型推导,右边初始化。为了解决这个问题,C++14新增了一个decltype(auto)的形式,既可以精确推导出类型又能像auto一样,使用方便。
在C++14里面auto新增了一个使用场景,能够推导返回值的类型。这样在写复杂函数的时候会很省事。
C++14新增了字面量后缀“s”,表示标准字符串,可以通过auto str = "xxx"s;直接推导出std::string的类型。 decltype是auto的高级形式,更侧重于编译阶段的类型推导,所以常用在泛型编程里面,获取各种类型,配合typedef 或者using 更加方便。
在定义类的时候由于auto被禁止使用,可以使用decltype。
10.智能指针由于auto_ptr在资源转移过程中调用流程容易引出错误,C++11使用unique_ptr代替了auto_ptr。常用的两种智能指针,分别是unique_ptr和shared_ptr。 unqiue_ptr名字虽然听起来像指针,但实际上并不是指针,而是一个对象。离开作用域的时候自动释放。另外也没有定义加减运算,不能随意移动指针定制,避免指针越界等操作。也不能不初始化,声明候直接使用。
使用工厂函数make_unique()强制创建的时候必须初始化。make_unqiue()要求C++14。
unique_ptr表示的所有权是唯一的,不允许共享,unique_ptr应用了C++的转移语意,同时禁止拷贝赋值,在指向另外一个unique_ptr赋值的时候,必须用std::move()显示的转移所有权。转移之后原先的unique_ptr变成了空指针。
尽量不要对unique_ptr进行赋值操作,让其完全自动化管理指针。 shared_ptr和unique_ptr最大的不同点是:它的所有权可以被安全的共享,也就是说支持拷贝赋值。
shared_ptr通过使用“引用计数”,实现了安全共享。shared_ptr具有完整的“值语义”,所以它可以在任何场景替代原始指针,而不用再担心资源回收的问题,比如用于容器存储指针、用于函数安全返回动态创建的对象。 shared_ptr的引用计数的存储和管理都是有成本的,过度的使用shared_ptr会降低运行效率。 shared_ptr的引用计数销毁在运行阶段会变得很复杂,很难确定真正释放资源的时机。如果析构函数有非常复杂,严重阻塞的操作,一旦shared_ptr在某个不确定的时间点析构释放资源,就会阻塞整个进程或者线程。 11.Lambda表达式lambda表达式就地定义函数,限制它的作用域和生命周期,实现函数的局部化。 lambda表达式用起来也就更灵活自由,能对它做各种运算,生成新的函数。这就像是数学里的复合函数那样,把多个简单功能的小lambda表达式组合,变成一个复杂的大lambda表达式。 lambda表达式除了可以像普通函数一样使用外,还可以捕获外部变量
因为lambda表达式不是普通的变量,C++也鼓励程序员尽量匿名使用lambda表达式。也就是不必显示的命名,直接就地使用。我们可以使用STL+lambda来替代for循环。
建议你在使用捕获功能的时候要小心,对于“就地”使用的小lambda表达式,可以用“[&]”来减少代码量,保持整洁;而对于非本地调用、生命周期较长的lambda表达式应慎用“[&]”捕获引用,而且,最好是在“[]”里显式写出变量列表,避免捕获不必要的变量。 虽然目前在C++里,纯函数式编程还比较少见,但“轻度”使用lambda表达式也能够改善代码,比如用“map+lambda”的方式来替换难以维护的if/else/switch,可读性要比大量的分支语句好得多。
lambda表达式的返回值类型可以自动推导(相当于用了auto),但有的时候必须明确指定返回值类型,在入口参数的圆括号后用“->type”的形式。 在按值捕获外部变量的时候,可以给lambda表达式加上mutable修饰,允许修改变量。注意,这与按引用捕获不同,修改的只是变量的拷贝,不影响外部变量的原值。 因为每个Iambda表达式的类型都是唯一的,所以即使函数签名相同,lambda变量也不能互相赋值。解决办法是使用标准库里的stdl:function类,它是“函数的容器”“智能函数指针”,可以存储任意符合签名的"可调用物"(callableobject)搭配使用能够让lambda表达式用起来更灵活。 |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 3:52:30- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |