C++证道之路第十八章探讨C++新标准

news2024/11/24 12:50:48

一、复习前面介绍过的C++11新功能

1、新类型

C++11新增了类型long long 和unsigned long long

新增了类型char16_t 和char32_t

2、统一的初始化

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

3、声明

auto 以前时一个储存类型的说明符,C++11将其用于实现自动类型推断。

decltype 将变量的类型声明为表达式指定的类型。

指定返回类型:

C++11新增了一种函数声明语法;在函数名和参数列表后面指定返回类型

using

nullptr

4、智能指针

如果在程序中使用new从堆(自由存储区)分配内存,等到不再需要时,应使用delete将其释放。C++引入了智能指针auto_ptr以帮助自动完成这个过程。C++11摒弃了auto_ptr,并新增了unique_ptr,shared_ptr,weak_ptr。

5、异常规范方面的修改

noexcept

6、作用域内枚举

枚举名的作用域为枚举定义所属的作用域,这意味着如果在同一个作用域内定义两个枚举,它们的枚举成员不能同名。最后,枚举可能不是可完全移植的,因为不同的实现可能选择不同的底层类型。未解决这些问题C++11新增了一种枚举。这种枚举使用class或struct定义。

enum old {yes,no,maybe};
enum class new1 {never, sometime, often, always};
enum struct new2 {never , lever , sever};
7、对类的修改

通过使用类内初始变化,可避免在构造函数中编写重复的代码,从而降低了程序员的工作量、厌倦情绪和出错的机会。

如果构造函数再成员初始化列表中提供了相应的值,这些默认值将被覆盖,因此第三个构造函数覆盖了类内成员初始化。

8、模板和STL方面的修改

基于范围的for循环

新的STL容器

新的STL方法

valarray升级

摒弃export

尖括号

9、右值引用

C++11新增了右值引用,这是使用&&表示的。右值引用可关联到右值,即可出现在赋值表达式右边,但不能对其应用地址运算符的值。右值包括字面常量,注入x+y等表达式以及返回值的函数(条件是函数赶回的不是引用)。

二、移动语义和右值引用
1、为何需要移动语义

在移动语义之前,当我们想要传递一个对象(特别是含有动态分配资源的对象,如std::vectorstd::string等)时,我们通常会使用拷贝构造或拷贝赋值操作,这可能会涉及大量的内存分配和数据复制,从而导致性能问题。

移动语义通过允许对象“移动”其资源而不是复制它们来避免这些性能问题。具体来说,当一个对象被“移动”时,它将其内部资源(如动态分配的内存、文件句柄等)的所有权转移给另一个对象,而不是复制这些资源。原始对象在移动后通常被置于有效的但不确定的状态,并且不应再被使用(除非重新初始化)。

C++11通过引入右值引用(rvalue reference)和移动构造函数(move constructor)以及移动赋值操作符(move assignment operator)来支持移动语义。右值引用使用&&符号表示,它们绑定到临时对象(如返回值、字面量等)的右值。

2、一个移动示例
std::vector<int> foo() {  
    std::vector<int> v = {1, 2, 3, 4, 5};  
    return v; // 这里返回的是v的右值引用,可以触发移动语义  
}  
  
int main() {  
    std::vector<int> v1 = foo(); // 这里可能使用移动构造函数来初始化v1  
    std::vector<int> v2;  
    v2 = std::move(v1); // 这里使用移动赋值操作符将v1的资源移动给v2  
    // 现在v1处于有效但不确定的状态,不应再使用  
    return 0;  
}
3、移动构造函数解析

虽然使用右值引用可以支持移动语义,但这并不会神奇的发生。要让移动语义发生需要两个步骤。首先,右值引用让不变一起知道何时可使用移动语义。

通过提供一个使用左值引用的构造函数和一个使用右值引用的构造函数,将初始化分为了两组。使用左值对象初始化对象时,将使用复制构造函数,而时候用右值对象初始化对象时,将使用移动构造函数,程序员可根据需要赋予这些构造函数不同的行为。

4、赋值

适用于构造函数的移动语义考虑也适用于赋值运算符。

5、强制移动

move()

三、新的类功能

1、特殊成员函数

在原有4个特殊成员函数(默认构造函数、复制构造函数、复制赋值运算符和析构函数)的基础上,C++11新增了两个:移动构造函数和移动赋值运算符。

2、默认的方法和禁用的方法

default

3、委托构造函数

C++11允许在一个构造函数的定义中使用另一个构造函数。这被称为委托,因为构造函数暂时将创建对象的工作委托给另一个构造函数。

4、继承构造函数

派生类继承基类的所有的构造函数(默认构造函数、复制构造函数和移动构造函数除外),但不会使用于派生类构造函数的特征标匹配的构造函数。

5、管理虚方法:override 和final

虚方法对实现多态类层次结构很重要,让基类引用或指针能够根据指向的对象类型调用相应的方法,但虚方法也带来了一些编程陷阱。例如,假设基类声明了一个虚方法,而你决定在派生类中提供不同的版本,这将覆盖旧版本。如果特征标不匹配,将隐藏而不是覆盖旧版本。

四、lambda函数

1、比较函数指针、函数符和lambda函数

函数指针是指向函数的指针,它允许你通过指针来调用函数。

简洁明了,直接指向函数

可以在不修改代码的情况下改变函数的行为(通过改变指针的指向)

只能指向全局函数或静态成员函数,不能指向类的非静态成员函数(因为非静态成员函数需要一个隐式的this指针)

不支持状态封装(即它们不能存储自己的数据)

语法相对繁琐

函数对象是一个重载了operator()的类对象,使得它像函数一样可以被调用

可以封装状态(即它们可以存储自己的数据)

可以作为类的成员,从而可以访问类的私有和保护成员

可以拥有构造函数、析构函数和其他成员函数,提供更多的灵活性

需要定义类,这可能会增加代码的复杂性

相对于lambda函数,它们可能更冗长

Lambda函数是C++11引入的一种匿名函数对象,它可以在需要的地方定义,并立即使用

简洁明了,可以在需要的地方直接定义

支持捕获列表,可以捕获外部作用域中的变量,使得lambda可以访问这些变量的值(或引用)

语法简洁,易于阅读和理解

可以作为参数传递给函数或赋值给函数指针和函数对象

由于是匿名的,所以不能在定义它的作用域之外被直接引用

捕获列表可能会增加额外的开销(特别是如果捕获的是大型对象或复杂类型)

2、为何使用lambda

函数指针适用于简单的全局函数或静态成员函数的调用。函数对象提供了更多的灵活性和状态封装,但可能需要更多的代码。Lambda函数则提供了一种简洁、灵活的方式来定义和使用可调用实体,特别是在需要捕获外部变量的情况下。在可能的情况下,lambda函数通常是首选的可调用实体,因为它们易于阅读、理解和使用。

五、包装器

包装器(Wrapper)通常是一个类或者函数,它封装了另一个类型或资源的接口,并可能提供了额外的功能或管理。

1、包装器function 及模板的低效性
answer = ef(q);

ef是什么呢?它可以是函数名,函数指针。函数对象或有名称的lambda表达式。所有这些都是可调用的类型。鉴于可调用的类型如此丰富,这可能导致模板的效率极低。

2、修复问题

3、其他方式

六、可变参数模板

可变参数模板能够创建模板函数和模板类,即可接受可变数量的参数。

要创建可变参数模板,需要理解几个要点:

模板参数包

函数参数包

展开参数包

递归

1、模板和函数参数包

函数参数包是C++11引入的一个特性,允许我们定义一个函数,该函数可以接受任意数量和类型的参数。参数包使用模板参数和三个点(...)语法。

template <typename... Args>  
void print(Args... args) {  
    (std::cout << ... << args) << '\n';  
    // 注意:上面的折叠表达式是C++17中的语法  
    // 在C++11/14中,你可能需要使用递归终止函数或初始化列表技巧来实现类似的功能  
}  
  
int main() {  
    print(1, "hello", 3.14); // 输出:1hello3.14  
    return 0;  
}
2、展开参数包

使用递归模板特化来展开函数参数包

#include <iostream>  
  
// 终止特化  
template<typename T>  
void printHelper(T value) {  
    std::cout << value;  
}  
  
// 递归特化  
template<typename T, typename... Args>  
void printHelper(T value, Args... args) {  
    std::cout << value << " ";  
    printHelper(args...); // 递归调用,展开剩余参数  
}  
  
// 辅助函数,用于隐藏递归特化  
template<typename... Args>  
void print(Args... args) {  
    printHelper(args...); // 展开参数包  
    std::cout << std::endl;  
}  
  
int main() {  
    print(1, "hello", 3.14); // 输出:1 hello 3.14  
    return 0;  
}
使用折叠表达式来展开函数参数包
#include <iostream>  
  
template<typename... Args>  
void print(Args... args) {  
    (std::cout << ... << args) << std::endl; // 折叠表达式  
}  
  
int main() {  
    print(1, "hello", 3.14); // 输出:1hello3.14  
    return 0;  
}
3、在可变参数模板函数中使用递归
#include <iostream>  
  
// 递归终止函数  
template<typename T>  
void print_element(T value) {  
    std::cout << value << " ";  
}  
  
// 递归函数模板  
template<typename T, typename... Args>  
void print_elements(T value, Args... args) {  
    // 处理当前元素  
    print_element(value);  
    // 递归调用以处理剩余元素  
    if constexpr (sizeof...(args) > 0) { // C++17及更高版本中的if constexpr  
        print_elements(args...);  
    }  
}  
  
// 辅助函数模板,用于隐藏递归细节  
template<typename... Args>  
void print(Args... args) {  
    print_elements(args...);  
    std::cout << std::endl; // 输出换行  
}  
  
int main() {  
    print(1, "hello", 3.14); // 输出:1 hello 3.14 (后接换行)  
    return 0;  
}

七、C++11新增的其他功能

1、并行编程

C++并行编程涉及使用C++语言来编写能够同时执行多个任务(或线程)的程序,以加快程序的执行速度或更有效地利用计算资源。C++标准库本身并没有直接提供并行编程的API,但有一些库和工具可以帮助开发者实现并行性。

2、新增的库

正则表达式

正则表达式指定了一种模式,可用于与文本字符串的内容匹配。

3、低级编程

低级编程中的“低级”指的是抽象程度,而不是编程质量。低级意味着接近于计算机硬件和机器语言使用的比特和字节。对嵌入式编程和改善操作的效率而言,低级编程很重要。

4、杂项

元编程

八、语言变化

1、boost项目

2、TR1

是一个库扩展选集

3、使用boost

九、接下来的任务

用例分析,CRC卡

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1647430.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据Spark教程从入门到精通第三篇:Spark核心模块

一&#xff1a;Spark核心模块 1&#xff1a;概述 Spark最底层的模块是Apache Spark Core&#xff0c;其他的功能都是基于此实现的。 Spark SQL操作结构化数据的模块 Spark Streaming 对流式数据处理的模块。 Spark MLlib对机器学习支持的一个功能模块。学习难度很高 Spark Gra…

dumpsys meminfo 流程中细节

源码基于&#xff1a;Android U 参考&#xff1a; dumpsys meminfo 详解(R) dumpsys meminfo 详解(U) 1. 命令入口 MemBinder frameworks/base/services/core/java/com/android/server/am/AMS.javastatic class MemBinder extends Binder {ActivityManagerService mActivity…

Python-VBA函数之旅-print函数

目录 一、print函数的常见应用场景 二、print函数使用注意事项 三、如何用好print函数&#xff1f; 1、print函数&#xff1a; 1-1、Python&#xff1a; 1-2、VBA&#xff1a; 2、推荐阅读&#xff1a; 个人主页&#xff1a;神奇夜光杯-CSDN博客 一、print函数的常见应…

Prometheus 2: 一个专门评估其他语言模型的开源语言模型(续集)

普罗米修斯的续集来了。 专有的语言模型如 GPT-4 经常被用来评估来自各种语言模型的回应品质。然而,透明度、可控制性和可负担性等考虑强烈促使开发专门用于评估的开源语言模型。另一方面,现有的开源评估语言模型表现出关键的缺点:1) 它们给出的分数与人类给出的分数存在显著差…

Unity射击游戏开发教程:(11)制造敌人爆炸

增加爆炸效果 爆炸一切都变得更好!尤其是当你消灭敌人时。在这篇文章中,我将讨论如何在敌人被击中时为其添加爆炸动画。 在敌人的预制件中,您将需要创建一个新的动画。查看控制动画的动画器,默认情况下将从进入动画到敌人爆炸动画。这意味着,一旦敌人被实例化,敌人爆炸…

02、Kafaka 简介

02、Kafka 简介 1、 Kafka 简介 Apache Kafka 是一个分布式的发布-订阅消息系统&#xff0c;最初由 LinkedIn 公司开发&#xff0c;并在 2010 年贡献给了 Apache 软件基金会&#xff0c;成为一个顶级开源项目。Kafka 设计之初是为了满足高吞吐量、可扩展性、持久性、容错性以…

深度学习中的不确定性量化:技术、应用和挑战综述(一)

不确定性量化(UQ)在减少优化和决策过程中的不确定性方面起着关键作用&#xff0c;应用于解决各种现实世界的科学和工程应用。贝叶斯近似和集成学习技术是文献中使用最广泛的两种UQ方法。在这方面&#xff0c;研究人员提出了不同的UQ方法&#xff0c;并测试了它们在各种应用中的…

10.Java对象内置结构

文章目录 Java对象内置结构1.Java对象的三个部分1.1.对象头1.2.对象体1.3.对齐字节 2.对象结构中核心字段的作用2.1.MarkWord(标记字)2.2.Class Pointer(类对象指针)2.3.Array Length(数组长度)2.4.对象体2.5.对齐字节 3.Mark Word的结构信息3.1.不同锁状态下的Mark Word字段结…

GraphGPT——图结构数据的新语言模型

在人工智能的浪潮中&#xff0c;图神经网络&#xff08;GNNs&#xff09;已经成为理解和分析图结构数据的强大工具。然而&#xff0c;GNNs在面对未标记数据时&#xff0c;其泛化能力往往受限。为了突破这一局限&#xff0c;研究者们提出了GraphGPT&#xff0c;这是一种为大语言…

部署YUM仓库以及NFS共享服务

YUM仓库部署 一.YUM概述 YUM仓库源是一种软件包管理工具&#xff0c;用于在Linux系统上安装、更新和删除软件包。YUM仓库源包含了软件包的元数据信息和实际的软件包文件。用户可以通过配置YUM仓库源&#xff0c;从中下载和安装软件包。 常见的YUM仓库源包括&#xff1a; 本…

pip install dotenv出现error: subprocess-exited-with-error的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

springboot+vue+elementui实现校园互助平台大作业、毕业设计

目录 一、项目介绍 二、项目截图 管理后台 1.登录&#xff08;默认管理员账号密码均为&#xff1a;admin&#xff09; 2. 用户管理 ​编辑 3.任务管理 互助单&#xff08;学生发布&#xff09; 行政单&#xff08;教师发布&#xff09; ​编辑 审核&#xff08;退回需…

36.Docker-Dockerfile自定义镜像

镜像结构 镜像是将应用程序及其需要的系统函数库、环境、配置、依赖打包而成。 镜像是分层机构&#xff0c;每一层都是一个layer BaseImage层&#xff1a;包含基本的系统函数库、环境变量、文件系统 EntryPoint:入口&#xff0c;是镜像中应用启动的命令 其他&#xff1a;在…

电脑c盘太满了,如何清理 电脑杀毒软件哪个好用又干净免费 电脑预防病毒的软件 cleanmymacX有必要买吗 杀毒软件排行榜第一名

杀毒软件通常集成监控识别、病毒扫描和清除、自动升级、主动防御等功能&#xff0c;有的杀毒软件还带有数据恢复、防范黑客入侵、网络流量控制等功能&#xff0c;是计算机防御系统的重要组成部分。 那么&#xff0c;对于Mac电脑用户来说&#xff0c;哪款电脑杀毒软件更好呢&a…

PCB光控打孔机第二版程序(一)

/*PCB机程序 XY同时启动 L9751 CODE61068 2018 6 19 08:00 固定位置释放吸盘*/ /*修正寻点第十二条结束调用计算坐标L5091&#xff0c;自动运行Y计算L6280 6281***/ /*** 开外部中断2关闭定时器2XY轴输出信号&#xff0c;自动运行循环检测外部中断高电平重启XY轴输出信号 增加寻…

LeetCode 难题解析 —— 正则表达式匹配 (动态规划)

10. 正则表达式匹配 思路解析 这道题虽然看起来不难理解&#xff0c;但却存在多种可能&#xff0c;当然这种可能的数量是有限的&#xff0c;且其规律对于每一次判别都使用&#xff0c;所以自然而然就想到用 动态规划 的方法啦 接下来逐步分析可能的情况&#xff1a; &#x…

探索中位数快速排序算法:高效寻找数据集的中间值

在计算机科学领域&#xff0c;寻找数据集的中位数是一个常见而重要的问题。而快速排序算法作为一种高效的排序算法&#xff0c;可以被巧妙地利用来解决中位数查找的问题。本文将深入探讨中位数快速排序算法的原理、实现方法以及应用场景&#xff0c;带你领略这一寻找中间值的高…

[UDS][OTA] 自定义 IntelHEX (IHEX) format read/write library in C

参考修改 参考github的MIT协议开源项目 ihex 改写的代码 https://gitee.com/liudegui/intelhex-c 修改点&#xff1a; 修改Makefile脚本&#xff0c;支持x86_X64平台和aarch64平台将默认读取行长度设置为16位删除与ihex和bin之间的转换无关的示例代码 十六进制描述 HEX格式…

C++容器——deque

deque容器 定义&#xff1a;动态数组&#xff0c;是一种双向开口的线性容器&#xff0c;意味着你不仅可以像在普通队列的末尾添加和移除元素&#xff0c;还可以在前端执行这些操作。 与其他容器相比不同的点&#xff1a; 与vector的主要区别&#xff1a; 连续性&#xff1a;…

基于 Spring Boot 博客系统开发(六)

基于 Spring Boot 博客系统开发&#xff08;六&#xff09; 本系统是简易的个人博客系统开发&#xff0c;为了更加熟练地掌握 SprIng Boot 框架及相关技术的使用。&#x1f33f;&#x1f33f;&#x1f33f; 基于 Spring Boot 博客系统开发&#xff08;五&#xff09;&#x1f…