百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 编程网 > 正文

c++11新特性总结,你都用过哪些新特性?

yuyutoo 2024-12-14 15:53 4 浏览 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";
}

相关推荐

墨尔本一华裔男子与亚裔男子分别失踪数日 警方寻人

中新网5月15日电据澳洲新快网报道,据澳大利亚维州警察局网站消息,22岁的华裔男子邓跃(Yue‘Peter’Deng,音译)失踪已6天,维州警方于当地时间13日发布寻人通告,寻求公众协助寻找邓跃。华...

网络交友须谨慎!美国犹他州一男子因涉嫌杀害女网友被捕

伊森·洪克斯克(图源网络,侵删)据美国广播公司(ABC)25日报道,美国犹他州一名男子于24日因涉嫌谋杀被捕。警方表示,这名男子主动告知警局,称其杀害了一名在网络交友软件上认识的25岁女子。雷顿警...

一课译词:来龙去脉(来龙去脉 的意思解释)

Mountainranges[Photo/SIPA]“来龙去脉”,汉语成语,本指山脉的走势和去向,现比喻一件事的前因后果(causeandeffectofanevent),可以翻译为“i...

高考重要考点:range(range高考用法)

range可以用作动词,也可以用作名词,含义特别多,在阅读理解中出现的频率很高,还经常作为完形填空的选项,而且在作文中使用是非常好的高级词汇。...

C++20 Ranges:现代范围操作(现代c++白皮书)

1.引言:C++20Ranges库简介C++20引入的Ranges库是C++标准库的重要更新,旨在提供更现代化、表达力更强的方式来处理数据序列(范围,range)。Ranges库基于...

学习VBA,报表做到飞 第二章 数组 2.4 Filter函数

第二章数组2.4Filter函数Filter函数功能与autofilter函数类似,它对一个一维数组进行筛选,返回一个从0开始的数组。...

VBA学习笔记:数组:数组相关函数—Split,Join

Split拆分字符串函数,语法Split(expression,字符,Limit,compare),第1参数为必写,后面3个参数都是可选项。Expression为需要拆分的数据,“字符”就是以哪个字...

VBA如何自定义序列,学会这些方法,让你工作更轻松

No.1在Excel中,自定义序列是一种快速填表机制,如何有效地利用这个方法,可以大大增加工作效率。通常在操作工作表的时候,可能会输入一些很有序的序列,如果一一录入就显得十分笨拙。Excel给出了一种...

Excel VBA入门教程1.3 数组基础(vba数组详解)

1.3数组使用数组和对象时,也要声明,这里说下数组的声明:'确定范围的数组,可以存储b-a+1个数,a、b为整数Dim数组名称(aTob)As数据类型Dimarr...

远程网络调试工具百宝箱-MobaXterm

MobaXterm是一个功能强大的远程网络工具百宝箱,它将所有重要的远程网络工具(SSH、Telnet、X11、RDP、VNC、FTP、MOSH、Serial等)和Unix命令(bash、ls、cat...

AREX:携程新一代自动化回归测试工具的设计与实现

一、背景随着携程机票BU业务规模的不断提高,业务系统日趋复杂,各种问题和挑战也随之而来。对于研发测试团队,面临着各种效能困境,包括业务复杂度高、数据构造工作量大、回归测试全量回归、沟通成本高、测试用例...

Windows、Android、IOS、Web自动化工具选择策略

Windows平台中应用UI自动化测试解决方案AutoIT是开源工具,该工具识别windows的标准控件效果不错,但是当它遇到应用中非标准控件定义的UI元素时往往就无能为力了,这个时候选择silkte...

python自动化工具:pywinauto(python快速上手 自动化)

简介Pywinauto是完全由Python构建的一个模块,可以用于自动化Windows上的GUI应用程序。同时,它支持鼠标、键盘操作,在元素控件树较复杂的界面,可以辅助我们完成自动化操作。我在...

时下最火的 Airtest 如何测试手机 APP?

引言Airtest是网易出品的一款基于图像识别的自动化测试工具,主要应用在手机APP和游戏的测试。一旦使用了这个工具进行APP的自动化,你就会发现自动化测试原来是如此简单!!连接手机要进行...

【推荐】7个最强Appium替代工具,移动App自动化测试必备!

在移动应用开发日益火爆的今天,自动化测试成为了确保应用质量和用户体验的关键环节。Appium作为一款广泛应用的移动应用自动化测试工具,为测试人员所熟知。然而,在不同的测试场景和需求下,还有许多其他优...

取消回复欢迎 发表评论: