c++11新特性总结,你都用过哪些新特性?
yuyutoo 2024-12-14 15:53 1 浏览 0 评论
很多进入 C++ 领域的朋友都是从 C 转行而来,会天然地将 C 的语法用在 C++ 代码中。
随着 C++ 的现代化进程在加快,前段时间有些朋友和我提起,现在的 C++ 语法他/她已经看不懂了。
所以,有必要让初进 C++ 的朋友对 C++ 语言的现代化版本有更全面的认识,藉此机会,我们就一起聊聊现代化的起点版本 C++ 11 引入了哪些比较有用的新特性?
1. Lambda 表达式
Lambda 表达式其实就是无名函数,如果函数名字对于使用者来说没有意义,就很适合使用 Lambda 表达式替代。
比如往接口 interface() 传递回调函数时,以往一般采用传递函数地址,需要专门定义一个函数,特意为它起名还想了很久,而且自己从来不调用它,就很尴尬。
有了 Lambda 表达式,你可以:
interface([](int x, int y) { return x + y; });
2. enum class
之前我们使用的枚举 enum 有个非常让人懊恼的问题:
cppenum Color { Red, Blue, Green, Yellow };
enum TrafficLights { Red, Yellow, Green };
这样的定义会导致编译错误,因为枚举值的作用域是公共的,在 Color 中定义的枚举值 Red 会和 TrafficLights 中定义的 Red 之间有命名冲突。
C++ 11 引入了 enum class 强类型枚举,可以有效避免命名冲突,因为所有枚举值都被声明在特定的作用域内,引用时必须使用作用域解析符:
cppColor c = Color::Red;
除此之外,传统的枚举值可以被隐式转换成整数类型,而强类型枚举不能隐式转换,如需转换可用 static_cast:
cppint val = static_cast<int>(Color::Red);
3. 范围 for 循环
在之前的版本里,for 循环有很死板的写法,以遍历容器 vector 为例:
cppstd::vector<int> v(5, 2);
for (std::vector<int>::iterator i = v.begin(); i != v.end(); ++ i) {
std::cout << *i << " ";
}
基本格式是:
for (初始化语句; 循环条件判断; 执行语句) {}
C++ 11 把 for 循环的格式扩展添加了对范围的遍历,改写上面的例子:
cppstd::vector<int> v(5, 2);
for (int i : v) {
std::cout << i << " ";
}
范围 for 循环的写法简化了对容器、数组等类型数据的遍历。
4. 自动类型推导 auto
很多时候有些类型书写起来会很长,然后又要大量使用,想想都觉得头皮发麻。
就比如上面对容器执行迭代时,需要获取容器的迭代器,这个迭代器的类型是定义在容器内部的,声明容器的迭代器要书写的篇幅会很长,很不利于阅读:
std::vector<int>::iterator i;
所以,C++ 11 赋予了关键词 auto 新的功能,只要使用 auto 声明变量,编译器就可以自动推导变量的类型,减少代码的冗余。
比如下面的表达式中,编译器可以依据右侧的操作数推断左侧新建的变量类型:
cppauto x = 5; // int
auto y = 3.14; // double
5. 空指针 nullptr
传统的代码里,我们随处可见到空指针的引用,比如常用于表示空指针的宏定义 NULL:
cpp#define NULL 0
或者
cpp#define NULL (void*)0
无论定义成哪种,编译器可以隐式将其转换成整形或者任何类型的指针,这是类型不安全的。
如果类内重载了这样一个方法:
cpp// 声明 function
function(int x);
function(char *x);
那么调用时传入 NULL,编译器应该选择哪个方法?
cppfunction(NULL);
NULL 的用意不明确,同时也会带来阅读困难。
所以,C++ 11 引入了关键词 nullptr 专门表示空指针,它不能隐式转换成整形,也就没有了语义不明的问题。
cppint* p = nullptr;
若大家觉得看文章不过瘾,可以来拿C/C++视频学习包,给大家整理了一个教程合集(内含:C++基础,网络编程,数据库,组件,中间件,框架,分布式架构,项目实战等)↓看下图↓↓↓↓↓↓↓。
6. constexpr
以往的代码里,有时想定义一个长度由变量定义的数组:
cppint array[num];
但是,这样的代码在 C++ 11 之前,编译器是会报错的。
还有,如果定义了一个函数执行计算:
cppint square(int x) {
return x * x;
}
调用时如果输入的参数是常量,难道非得要在运行时才费时执行计算吗?
cppint area = square(9);
C++ 11 引入了新关键词 constexpr,表示常量表达式,目标是榨干编译器的性能,减轻运行时负担,达到性能优化。
使用 constexpr 修饰变量,该变量在编译期就确定了值,在所有引用位置都会直接嵌入代码中,因而可以用于数组的长度定义。而 const 修饰的变量允许在运行时才确定。
cppconstexpr int array[num];
而使用 constexpr 修饰函数,在调用该函数并输入常量或者 constexpr 修饰的量时,编译器会尝试执行计算并返回结果,这样运行时又可省略计算负担而直接得到结果:
cppconstexpr int square(int x) {
return x * x;
}
int area = square(9);
7. 新关键词 override、final、noexcept
- override 作为修饰词放在函数声明的末尾,声明当前函数是父类虚函数的重写,促使编译器去检查父类中是否有这样的虚函数,如果没有则报错。
class Base {
public:
virtual void func() const { ... } // 基类虚函数
};
class Derived : public Base {
public:
void func() const override { ... }
};
- final 作为修饰词放在类名或者函数声明的末尾,它的作用是防止类被进一步继承或虚函数被进一步重写。
class Base {
virtual void func() { ... }
};
class Derived1 : public Base {
virtual void func() final {
// Derived1::func() 是最后一个版本
// Derived1 的任何派生类中都不能再重写 func()
}
};
class Derived2 final : public Derived1 {
// Derived2 是最终类,不能再被继承
};
- noexcept 作为修饰词放在函数声明的末尾,显式声明函数在任何情况下都不会抛出异常。
class MyClass {
public:
MyClass(MyClass&&) noexcept = default; // 确保移动构造不会抛异常
~MyClass() noexcept = default; // 确保析构不会抛异常
};
使用修饰符 noexcept 有什么好处吗?
标准库里有些操作,在发生错误时,要求能够回滚操作,这样就需要安全的操作,包括不会抛出异常的操作,所以声明为 noexcept 的函数是客观需要的。
另外,移动操作比拷贝操作要有效率,但标准库在无法确定安全性的情况下,会选择更慢但更安全的拷贝操作,所以声明为 noexcept 的函数也对性能优化有帮助。
如果被声明为 noexcept 的函数却抛出了异常,系统会调用 terminate() 终止进程。
8. 统一的初始化语法
在传统的写法里,为了创建对象,会经常使用小括号 () 语法初始化对象,目的是调用构造函数初始化对象,但是有时会与函数声明产生混肴:
struct S {
S(int, int) {}
};
S obj1(1, 2); // 构造一个 S 对象
S obj2(); // 这是函数声明,函数名为 obj2,返回类型为 S 的对象
这种初始化的方式有很大的弊端。
有时初始化赋值,又有可能从较大范围的值隐式转换为较小范围的值,也就是窄化转换,会引发潜在的错误:
cppint x = 3.14; // 允许,x 将变为 3
在 C++ 11 之前,花括号 {} 主要用于数组初始化、聚合类型(如结构体)的初始化,以及通过构造函数的初始化列表进行成员初始化。
C++ 11 引入了统一初始化(也称为列表初始化),使得花括号可以在各种情况下使用,简化了不同类型的初始化方式,例如对象、数组、类成员等,都可以使用花括号进行初始化。
更重要的是,统一初始化解决了上面遇到的那些典型问题。
S obj3{1, 2}; // 明确表示构造一个 S 对象
int y{3.14}; // 错误,编译器禁止窄化转换
9. 右值引用 &&
在传统的写法里,有对左值的引用操作,但是缺乏对右值的引用操作,右值引用能优化对资源的使用,所以 C++ 11 引入了右值引用符号,用 && 表示。
比如定义类的移动构造函数时,需要将形参声明为右值引用:
MyClass(MyClass&& other) noexcept : data(std::move(other.data)) {
std::cout << "Move Constructor\n";
}
- 上一篇:近代物理专题
- 下一篇:嵌入式C语言常用的5类预处理
相关推荐
- 史上最全的浏览器兼容性问题和解决方案
-
微信ID:WEB_wysj(点击关注)◎◎◎◎◎◎◎◎◎一┳═┻︻▄(页底留言开放,欢迎来吐槽)●●●...
-
- 平面设计基础知识_平面设计基础知识实验收获与总结
-
CSS构造颜色,背景与图像1.使用span更好的控制文本中局部区域的文本:文本;2.使用display属性提供区块转变:display:inline(是内联的...
-
2025-02-21 16:01 yuyutoo
- 写作排版简单三步就行-工具篇_作文排版模板
-
和我们工作中日常word排版内部交流不同,这篇教程介绍的写作排版主要是用于“微信公众号、头条号”网络展示。写作展现的是我的思考,排版是让写作在网格上更好地展现。在写作上花费时间是有累积复利优势的,在排...
- 写一个2048的游戏_2048小游戏功能实现
-
1.创建HTML文件1.打开一个文本编辑器,例如Notepad++、SublimeText、VisualStudioCode等。2.将以下HTML代码复制并粘贴到文本编辑器中:html...
- 今天你穿“短袖”了吗?青岛最高23℃!接下来几天气温更刺激……
-
最近的天气暖和得让很多小伙伴们喊“热”!!! 昨天的气温到底升得有多高呢?你家有没有榜上有名?...
- CSS不规则卡片,纯CSS制作优惠券样式,CSS实现锯齿样式
-
之前也有写过CSS优惠券样式《CSS3径向渐变实现优惠券波浪造型》,这次再来温习一遍,并且将更为详细的讲解,从布局到具体样式说明,最后定义CSS变量,自定义主题颜色。布局...
- 你的自我界限够强大吗?_你的自我界限够强大吗英文
-
我的结果:A、该设立新的界限...
- 行内元素与块级元素,以及区别_行内元素和块级元素有什么区别?
-
行内元素与块级元素首先,CSS规范规定,每个元素都有display属性,确定该元素的类型,每个元素都有默认的display值,分别为块级(block)、行内(inline)。块级元素:(以下列举比较常...
-
- 让“成都速度”跑得潇潇洒洒,地上地下共享轨交繁华
-
去年的两会期间,习近平总书记在参加人大会议四川代表团审议时,对治蜀兴川提出了明确要求,指明了前行方向,并带来了“祝四川人民的生活越来越安逸”的美好祝福。又是一年...
-
2025-02-21 16:00 yuyutoo
- 今年国家综合性消防救援队伍计划招录消防员15000名
-
记者24日从应急管理部获悉,国家综合性消防救援队伍2023年消防员招录工作已正式启动。今年共计划招录消防员15000名,其中高校应届毕业生5000名、退役士兵5000名、社会青年5000名。本次招录的...
- 一起盘点最新 Chrome v133 的5大主流特性 ?
-
1.CSS的高级attr()方法CSSattr()函数是CSSLevel5中用于检索DOM元素的属性值并将其用于CSS属性值,类似于var()函数替换自定义属性值的方式。...
- 竞走团体世锦赛5月太仓举行 世界冠军杨家玉担任形象大使
-
style="text-align:center;"data-mce-style="text-align:...
- 学物理能做什么?_学物理能做什么 卢昌海
-
作者:曹则贤中国科学院物理研究所原标题:《物理学:ASourceofPowerforMan》在2006年中央电视台《对话》栏目的某期节目中,主持人问过我一个的问题:“学物理的人,如果日后不...
-
- 你不知道的关于这只眯眼兔的6个小秘密
-
在你们忙着给熊本君做表情包的时候,要知道,最先在网络上引起轰动的可是这只脸上只有两条缝的兔子——兔斯基。今年,它更是迎来了自己的10岁生日。①关于德艺双馨“老艺...
-
2025-02-21 16:00 yuyutoo
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- mybatis plus (70)
- scheduledtask (71)
- css滚动条 (60)
- java学生成绩管理系统 (59)
- 结构体数组 (69)
- databasemetadata (64)
- javastatic (68)
- jsp实用教程 (53)
- fontawesome (57)
- widget开发 (57)
- vb net教程 (62)
- hibernate 教程 (63)
- case语句 (57)
- svn连接 (74)
- directoryindex (69)
- session timeout (58)
- textbox换行 (67)
- extension_dir (64)
- linearlayout (58)
- vba高级教程 (75)
- iframe用法 (58)
- sqlparameter (59)
- trim函数 (59)
- flex布局 (63)
- contextloaderlistener (56)