【从零开始学习C++ | 第二十二篇】C++新增特性(下)

news2024/11/20 6:13:35

目录

前言:

类型推导:

constexpr关键字:

初始化列表:

基于范围的for循环:

智能指针之unique ptr

Lambda表达式:

总结:


前言:

        本文我们将继续介绍   C++ 11 新增十大特性的剩余六个,如果没有看过介绍前四个特性的小伙伴的可以点进我C++的专栏就可以看到。

类型推导:

类型推导(type inference)是 C++11 引入的一个重要特性,表示编译器可以根据上下文推断变量或表达式的类型。也就是说,在某些情况下,可以省略类型声明,直接使用关键字 auto 来定义变量或表达式,而编译器会自动推导该变量或表达式的类型。

使用类型推导可以减少代码中的重复性,并且可以使代码更加简洁和易读。使用类型推导时应该注意以下几点:

1. auto 关键字只能用于定义局部变量,不能用于定义类成员变量或全局变量。

2. 使用 auto 定义变量时,默认情况下变量是 const 类型,如果要定义非 const 类型变量,可以使用关键字 const_cast 来进行强制类型转换。

3. 由于编译器需要通过上下文推断变量类型,因此 auto 变量的初始化表达式必须完全明确,不能存在二义性。如果初始化表达式中有重载函数,编译器会根据函数的返回值类型来进行类型推导。

4. 在定义 auto 变量时,可以使用 decltype 关键字来指定变量的类型。

以下是一些使用类型推导的示例:

auto i = 10; // 推导出 i 的类型是 int
auto p = new int[10]; // 推导出 p 的类型是 int*
auto s = "hello"; // 推导出 s 的类型是 const char*
auto fun = [](int x) { return x + 1; }; // 推导出 fun 的类型是 lambda 表达式类型

总之,在某些情况下,使用类型推导可以使代码更加简洁明了,并且在降低代码重复性的同时还能提高代码可读性。注意需要谨慎使用类型推导,特别是在代码复杂或可读性要求较高的场合。

constexpr关键字:

constexpr 是一种 C++11 新增的关键字,用于使编译器在编译时计算常量表达式,从而提高代码效率。

在函数或变量声明时,constexpr 关键字可以用于声明一个常量表达式,例如:

constexpr int MAX_LEVEL = 100; // 声明一个常量表达式

constexpr int factorial(int n) {  // 声明一个返回值为常量表达式的函数
    return (n <= 1) ? 1 : n * factorial(n - 1);
}

使用 constexpr  关键字声明时,编译器会在编译时对表达式进行求值,而不是在程序运行时对其进行计算。这样可以在编译时就确定常量值,从而在运行时提高代码效率。

在 C++11 中,使用  constexpr  关键字定义常量表达式时,必须满足以下条件:

1. 表达式必须是一个纯量表达式。

2. 表达式的结果必须在编译时可知。

3. 表达式的求值必须产生一个值而不是一个副作用。

4. 函数返回值为 constexpr 类型的函数必须是由成文定义而非 inline 定义的。

使用  constexpr  关键字定义常量表达式的好处包括:

1. 编译时求解:由于在编译时计算常量表达式,可以避免在程序运行时进行计算,从而提高程序的运行效率。

2. 类型安全:使用 `constexpr` 关键字定义的常量表达式具有固定的类型,可以帮助程序员避免类型转换错误和运行时错误。

3. 代码简洁:使用 `constexpr` 关键字定义常量表达式可以简化代码,从而使程序更加易读易懂。

综上所述,`constexpr` 是非常有用的 C++11 特性,可以帮助程序员编写更高效、更安全的代码,在实际编程中应该加以充分利用。

这是一个很实用的关键字,用好了可以直接让性能起飞。

但其实他还有一个很实用的应用:实现动态数组。

因为他是在编译阶段就完成计算了,因此可以将他作为数组的大小参数而不会报错。这样我们就实现了动态数组。

constexpr  int pow (int x,int y)
{
    int result=x;
    while(--y>0)
    {
        result *=x;
    }
    return result;

}
int main()
{
    int a[pow(2,4)]    
    //我们在这里不就实现了动态数组。

}

初始化列表:

C++11 引入了初始化列表(initializer list)的概念,可以用来初始化一些标准容器、数组和自定义类型等对象。

初始化列表使用花括号  {}  来表示,可以在花括号中列出需要初始化的元素。以下是一些初始化列表的示例:

std::vector<int> v {1, 2, 3};  // 初始化一个包含三个元素的 vector 对象

int numbers[] {1, 2, 3}; // 初始化一个包含三个元素的整数数组

struct Point {
    int x;
    int y;
};

Point p {3, 4};  // 初始化一个自定义类型对象

初始化列表的好处主要有以下几点:

1. 初始化列表可以通过列表方式快速创建并初始化一个标准容器、数组或自定义类型的对象,简化了代码。

2. 初始化列表可以派生两个对象的初始化,例如可以使用首项列表来初始化一个 std::pair 对象,这样可以非常方便地初始化复合对象。

3. 初始化列表可以保证元素的顺序准确无误,而且可以确保元素的数量正确,避免了遗漏或重复,从而提高了程序的安全性。

需要注意的是,初始化列表不仅可以用于创建新对象,还可以用于赋值操作。例如,可以使用初始化列表来替代传统的赋值操作:

std::vector<int> v;
v = {1, 2, 3}; // 使用初始化列表来替代传统的赋值操作

总之,初始化列表是一个非常有用的 C++11 特性,可以简化代码的编写,避免了繁琐的初始化操作,并且提供了一种简单、可靠的方式来初始化容器、数组和自定义类型等对象。在实际编程中应该充分利用该特性。

基于范围的for循环:

C++11 引入了基于范围的 for 循环(range-based for loop)的特性,其语法形式为:

for (element : range) {
    // 循环体内容
}

其中,range 是一个 range 类别对象,element 表示从 range 中遍历出来的每个元素值。在循环体中可以直接使用 element 变量完成相应的操作。

使用基于范围的 for 循环的好处主要有以下几点:

1. 简化了代码:基于范围的 for 循环可以直接遍历数组和标准容器,避免了循环计数器的管理和手动访问容器或数组的元素,从而简化了代码。

2. 可靠性更高:基于范围的 for 循环可以避免越界访问和逻辑错误,从而提高了代码的可读性和可靠性。

3. 支持自定义类型:可以自定义一个类,从而实现让该类具有 range 类别的特性,然后可以在基于范围的 for 循环中使用该类的实例。

以下是一些基于范围的 for 循环的示例:

std::vector<int> v {1, 2, 3, 4, 5};
for (int i : v) {
    std::cout << i << " ";
}

int a[] {1, 2, 3, 4, 5};
for (int i : a) {
    std::cout << i << " ";
}

std::string str = "Hello, world!";
for (char c : str) {
    std::cout << c << " ";
}

总之,基于范围的 for 循环是 C++11 的一项非常实用的特性,可以大大简化代码,提高代码的可读性和可靠性。在实际编程中应该充分掌握并应用该特性。

智能指针之unique ptr

需要头文件  #include <memory>

智能指针是  C++11  引入的一个非常有用的特性,可以管理动态内存分配,避免内存泄漏和空指针的问题。其中,unique_ptr 是一种独占所有权的智能指针,用于管理动态分配的对象,具有以下特点:

1. unique_ptr 持有对象的所有权,即只有一个 unique_ptr 可以管理一个对象。

2. unique_ptr 通过 RAII(Resource Acquisition Is Initialization)机制来管理动态分配的对象,即在 unique_ptr 对象生命周期结束时,会自动释放所管理的对象。

3. unique_ptr 不支持共享所有权,即不能通过复制或赋值的方式将 unique_ptr 对象的所有权转移给其他 unique_ptr 对象。

以下是一些 unique_ptr 的使用示例:

std::unique_ptr<int> p(new int(10)); // 创建一个 unique_ptr

if (p) { // 判断指针是否为空
    std::cout << *p << std::endl; // 输出指针所指向的对象值
}

*p = 20; // 通过指针修改所指向对象值

std::unique_ptr<int> p2(std::move(p)); // 转移指针所有权

if (p2) { // 判断指针是否为空
    std::cout << *p2 << std::endl; // 输出指针所指向的对象值
}

释放 p2 管理的对象

p2.reset();

使用自定义删除器来释放动态分配的对象

std::unique_ptr<int, void(*)(int*)> p3(new int(30), [](int* p) { delete p; });

总之,unique_ptr 是 C++11 引入的一种非常有用的独占所有权智能指针,可以有效解决动态内存分配管理问题,规避内存泄漏和空指针的风险,提高程序的稳定性和可靠性。在实际编程中,应该充分掌握并应用 unique_ptr。

其实 unique_ptr  简而言之就是可以自动释放内存,避免了内存泄漏的风险。

#include<memeory>
using namespace std;
struct data
{
    int a,b,c;
};
void (f)
{
    unique_ptr<data> data (new data)
    {
        data->a=10;
        data->b=20;
        data->c=30;
    }
}

我们在这里就不需要手动释放内存。此外,我们还提供了另外一种方法构建一个智能指针:

 auto data = make_unique<data>();

这种写法避免了因为 data 构建失败而 抛出异常之后 出现 野指针。

关于智能指针其实还有很多知识点,我们在这里只是给大家简单讲解了一种智能指针。在后面会专门为大家写一篇文章讲解。

Lambda表达式:

Lambda 表达式是 C++11 引入的一种函数对象,主要用于简化函数对象的定义和传递。

Lambda 表达式由三部分组成:

1. 捕获列表(capture list):用于捕获一些外部变量或对象,可以为空。

2. 形参列表(parameter list):用于定义函数对象的形参列表,可以为空。

3. 函数体(function body):用于定义函数对象的实现,可以为空。

Lambda 表达式的定义方式为:

[capture list](parameters) -> return-type { function body }

其中,capture list 和 return-type 都是可选的,而 parameters 和 function body 则是必须的。以下是一些 Lambda 表达式的示例:

// 定义一个 Lambda 表达式
auto func = [](int x, int y) -> int { return x + y; };

// 使用 Lambda 表达式
int result = func(1, 2);
std::cout << result << std::endl;

// 定义一个带捕获列表的 Lambda 表达式
int a = 1, b = 2;
auto func2 = [a, &b](){ std::cout << a << b << std::endl; };

// 使用带捕获列表的 Lambda 表达式
func2();

Lambda 表达式的好处主要有以下几点:

1. 简化函数对象的定义:Lambda 表达式可以直接在需要的地方定义函数对象,避免了传统定义函数对象的繁琐和冗余。

2. 方便函数对象的传递:Lambda 表达式可以作为函数对象进行传递,从而避免了手动定义函数对象并传递的过程。

3. 支持捕获外部变量或对象:通过捕获列表,Lambda 表达式可以直接捕获外部作用域的变量或对象,方便编程。

总之,Lambda 表达式是 C++11 中非常实用的一项特性,可以简化函数对象的定义和传递,极大地提高了代码编写效率和代码可读性。在实际编程中应该充分掌握并应用该特性。

总结:

        本文我们详细的介绍了剩余的六个新增特性,其中有不少都是很实用的特性,如果用的好了可以大大简化代码的重复以及精简结构,因此我们要熟练的掌握这十个特性。

如果我的内容对你有帮助,请点赞,评论,收藏创作不易,大家的支持就是我坚持下去的动力!

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

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

相关文章

解决前端容器不能充满屏幕

解决前端容器不能充满屏幕 px、rpx、em、rem、vw、vh各种像素单位的区别 css3新单位vw、vh、vmin、vmax的使用详解 学习element-UI写管理系统的页面&#xff0c;发现当菜单栏都收缩起来&#xff0c;结果是这样的 红色框是容器里每个板块的布局&#xff0c;但是容器下面却有空白…

如何处理兼容性测试中的变更管理?

如何处理兼容性测试中的变更管理? 在进行软件测试的过程中&#xff0c;兼容性测试是&#xfeff;非常重要的一环。然而&#xff0c;在进行兼容性测试时&#xff0c;由于涉及到不同平台、不同设备的适配问题&#xff0c;可能会出现许多变更管理的情况。这时候&#xff0c;如果没…

阿里企业邮箱收费标准_企业邮箱费用明细表

阿里云企业邮箱收费标准&#xff08;免费版/标准/尊享/集团&#xff09;&#xff0c;2023阿里云企业邮箱收费标准&#xff0c;免费版企业邮箱0元&#xff0c;标准版企业邮箱540元一年&#xff08;原价600元一年&#xff09;&#xff0c;企业邮箱尊享版1400元一年&#xff0c;9折…

4-移动端适配-1

01-移动 Web 基础 谷歌模拟器 模拟移动设备&#xff0c;方便查看页面效果 屏幕分辨率 分类&#xff1a; 物理分辨率&#xff1a;硬件分辨率&#xff08;出厂设置&#xff09;逻辑分辨率&#xff1a;软件 / 驱动设置 结论&#xff1a;制作网页参考 逻辑分辨率 视口 作用&a…

微信小程序项目实例——2048小游戏

今日推荐&#x1f481;‍♂️ 第一次听廖俊涛的歌是他首次出现在明日之子舞台上的那首《谁》 到现在这首歌成了我网易云收藏的十几首歌中的一首&#xff0c;也是听的最多的一首 怎么形容呢&#x1f914;算不上惊艳&#xff0c;却百听不厌&#x1f442; &#x1f52e;&#x1…

直播美颜SDK的商业化应用:开发者需要注意的关键问题

直播美颜SDK是当前直播行业中十分热门的技术之一&#xff0c;它可以为直播平台提供高质量的美颜效果&#xff0c;提升直播用户的使用体验和观看体验。随着直播市场的不断扩大和竞争的加剧&#xff0c;越来越多的直播平台开始使用美颜SDK以提高自身的用户黏性和用户体验。那么&a…

二叉树OJ题:LeetCode--100.相同的树

朋友们、伙计们&#xff0c;我们又见面了&#xff0c;本期来给大家解读一下LeetCode中第100道二叉树OJ题&#xff0c;如果看完之后对你有一定的启发&#xff0c;那么请留下你的三连&#xff0c;祝大家心想事成&#xff01; 数据结构与算法专栏&#xff1a;数据结构与算法 个 人…

脑机接口:运动想象简介

脑机接口&#xff1a;运动想象简介 0. 脑机接口1. 运动想象2. 信号处理2.1 信号采集2.2 信号预处理2.3 特征提取2.4 分类识别 3. EEG波段介绍4. 脑电图电极定位5. 总结 0. 脑机接口 脑机接口&#xff08;Brain-Computer Interface&#xff0c; BCI&#xff09;&#xff1a;它是…

MATLAB 之 可视化图形用户界面设计

这里写目录标题 一、可视化图形用户界面设计1. 图形用户界面设计窗口1.1 图形用户界面设计模板1.2 图形用户界面设计窗口 2. 可视化图形用户界面设计工具1.1 对象属性检查器2.2 菜单编辑器2.3 工具栏编辑器2.4 对齐对象工具2.5 对象浏览器2.6 Tab 键顺序编辑器 3. 可视化图形用…

途乐证券|股票XR是什么意思?买股票为什么赚不到钱?

股票市场上有时会出现一些股票在其名称前加上英文字母的情况&#xff0c;比如XD、XR等。那么股票XR是什么意思&#xff1f;买股票为什么赚不到钱&#xff1f;途乐证券为大家准备了相关内容&#xff0c;以供参考。 股票XR是什么意思&#xff1f; 股票名称中带有XR是表示股票在进…

yolov5-cls部署之onnx导出

本文旨在介绍说明yolov5自带的分类如何导出动态的batch的onnx。其中输出两种形式&#xff1a; 形式&#xff08;1&#xff09;&#xff1a;导出带softmax映射到概率的 形式&#xff08;2&#xff09;&#xff1a;导出不带softmax的&#xff0c;这个也是官方默认的方式 一、动…

连接服务器,再连接VSCode

一、 创建账号&#xff0c;查找公钥 通过命令窗口 a. 打开你的 git bash 窗口 b. 进入 .ssh 目录&#xff1a;cd ~/.ssh c. 找到 id_rsa.pub 文件&#xff1a;ls d. 查看公钥&#xff1a;cat id_rsa.pub 或者 vim id_rsa.pub 查看本机 ssh 公钥&#xff0c;生成公钥 二、用…

Sangfor华东天勇战队:mybatis-plus demo

基本依赖添加&#xff0c;表创建&#xff0c;启动类&#xff0c;测试类 引入依赖&#xff1a; <!-- mybatis-plus 依赖--> <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version…

【vue2】封装文字过长自动省略部分并且鼠标悬浮显示全部

技术&#xff1a;Ant design vue1.7.8 UI框架、vue2.X 需求:实现文字过长自动省略部分&#xff0c;鼠标悬浮显示全部 效果图&#xff1a; 图一&#xff1a; 图二&#xff1a; 1.封装组件代码&#xff1a; src/components/Ellipsis/index.js 文件下代码 import Ellipsis f…

d2l_第七章学习_卷积神经网络

参考: d2l今日学习——卷积神经网络&#xff08;CNN&#xff09;https://blog.csdn.net/m0_61165991/article/details/124176077图像工程&#xff08;上册&#xff09;-图像处理傅里叶变换https://blog.csdn.net/qq_43369406/article/details/131350139 x.1 前储知识&#xff…

4-移动端适配-2

01-vw适配方案 vw和vh基本使用 vw和vh是相对单位&#xff0c;相对视口尺寸计算结果 vw&#xff1a;viewport width&#xff08;1vw 1/100视口宽度 &#xff09;vh&#xff1a;lviewport height ( 1vh 1/100视口高度 ) vw布局 vw单位的尺寸 px 单位数值 / ( 1/100 视口宽…

STM32:探索嵌入式开发的关键技术

在嵌入式系统开发领域&#xff0c;STMicroelectronics的STM32系列微控制器备受推崇。然而&#xff0c;对于初学者来说&#xff0c;全面掌握STM32并非易事。下面我们将探讨STM32的学习曲线&#xff0c;帮助您更好地理解其中的挑战与收获。 抽象层次的挑战&#xff1a;STM32是一…

光谱分析的统计学角度-1-统计学导论

统计分析以可见或不可见的形式存在于我们生活的各个方面&#xff0c;其可见的形式有数字化、图形化等分析方法&#xff0c;不可见的形式包括经验、常识和感觉。对于以实验数据为基础的光谱分析方法&#xff0c;统计分析是其理论分析和工程应用的基础&#xff0c;如何从统计学的…

网络安全能力成熟度模型介绍

一、概述 经过多年网络安全工作&#xff0c;一直缺乏网络安全的整体视角&#xff0c;网络安全的全貌到底是什么&#xff0c;一直挺迷惑的。目前网络安全的分类和厂家非常多&#xff0c;而且每年还会冒出来不少新的产品。但这些产品感觉还是像盲人摸象&#xff0c;只看到网络安…

综合使用各类方法,彻底关闭win10自动更新

目录 一&#xff1a;禁用window update服务 二&#xff1a;在策略中关闭win10自动更新的相关设置 三&#xff1a;任务计划内的Win10更新 四&#xff1a;在注册表中关闭Win10自动更新 结果&#xff1a; 另一种针对注册表的方法&#xff1a; 各个网站文章&#xff0c;作者找了很久…