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

这篇具有很好参考价值的文章主要介绍了【从零开始学习C++ | 第二十二篇】C++新增特性(下)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【从零开始学习C++ | 第二十二篇】C++新增特性(下),【从零开始学习C++】,学习,c++,开发语言,算法

目录

前言:

类型推导:

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 中非常实用的一项特性,可以简化函数对象的定义和传递,极大地提高了代码编写效率和代码可读性。在实际编程中应该充分掌握并应用该特性。

总结:

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

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

【从零开始学习C++ | 第二十二篇】C++新增特性(下),【从零开始学习C++】,学习,c++,开发语言,算法文章来源地址https://www.toymoban.com/news/detail-625057.html

到了这里,关于【从零开始学习C++ | 第二十二篇】C++新增特性(下)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【从零开始学习JAVA | 第二十五篇】泛型

    目录 前言: 泛型: 额外拓展: 总结:         本文将详细介绍之前我们在JAVA 中一直在讲的泛型,各位感兴趣的同学可以点击进来观看。         泛型是一种编程概念, 它允许在定义类、接口或方法时使用类型参数,这样可以在使用时指定实际的类型。 通过使用泛

    2024年02月16日
    浏览(32)
  • 【从零开始学习JAVA | 第二十九篇】Stream流

    目录 前言: Stram流: 设计目标: 使用步骤: 1.先得到一条Stream流,并把数据放上去。 2.利用Stream流中的各种API进行操作。 使用Stream流的注意事项: 总结:         本文我们将学习Stream流,他就像流水线一样,可以对我们要处理的对象进行逐步处理,最终达到我们想要的效果

    2024年02月17日
    浏览(36)
  • 【从零开始学习JAVA | 第二十三篇】集合体系结构

    目录 前言: 单列集合:      set与list的区别: 双列集合: map的特点: 总结:                   JAVA中为我们提供了很多集合,这些集合都有自己很独特的特点,因此我们要学习所有的集合,但是在学习所有的集合之前,我们还是先为大家介绍一下JAVA的集合体系结构,这

    2024年02月16日
    浏览(43)
  • 【从零开始学习JAVA | 第二十篇】常见API介绍 Math

    目录 前言:  MATH: Math类中的常用方法: 总结:                 本篇往后我们会详细介绍一些常用的API,今天我们介绍的是Math的常用方法。但是其实我们不需要记住所有的方法,在日常工作中自己学会查询API文档就可以了。 Math类是Java中提供的一个标准类, 它包含了许多

    2024年02月15日
    浏览(28)
  • 【从零开始学习JAVA | 第二十一篇】常见API介绍 System

    目录 前言: System: System类中静态方法: 总结:                 system 是一个很底层的 API,是一个工具类, 提供了一些与系统相关的方法 。他在我们写项目的时候提供了一些非常实用的方法,本篇将会介绍一些实用的system API 的方法调用。 System类是Java语言提供的一个

    2024年02月15日
    浏览(38)
  • 【从零开始学习JAVA | 第二十七篇】JAVA期末练习(PTA)

    目录 前言: R7-5 Count the letters in a string (统计字符串中的字符) R7-1 找素数 R7-3 电话号码同步(Java) 总结:         临近期末,我也更新一下PTA上的JAVA大题,希望各位都可以考出一个好的成绩。 (Count the letters in a string) (统计字符串中的字符) Write a method that counts th

    2024年02月16日
    浏览(36)
  • 从零开始学习 Java:简单易懂的入门指南之泛型及set集合(二十二)

    1.1泛型概述 泛型的介绍 ​ 泛型是JDK5中引入的特性,它提供了编译时类型安全检测机制 泛型的好处 把运行时期的问题提前到了编译期间 避免了强制类型转换 泛型的定义格式 类型: 指定一种类型的格式.尖括号里面可以任意书写,一般只写一个字母.例如: 类型1,类型2…: 指定多

    2024年02月09日
    浏览(27)
  • 【Kubernetes】第二十二篇 - k8s 部署 MySQL 服务(secret、deployment、service)

    上一篇,介绍基于 k8s 项目部署流程设计; 本篇,介绍 MySQL 服务的部署; 部署 MySQL 可以为指定 node 添加污点,专门用于 mysql 部署(当前只有一个节点,不考虑); 为了保证mysql容器重启时数据不会丢失:创建 mysql 数据目录,用于存储 mysql 数据,实现 MySQL 数据的持久化;

    2024年02月03日
    浏览(42)
  • 【从零开始学JAVA | 第二十四篇】单列集合的遍历

    目录 前言: 单列集合的遍历方式: 迭代器遍历: 增强for遍历: lambda方法遍历:  总结: 本篇我们会讲解关于单列集合的几种遍历方式,遍历集合可以说是对于集合要求掌握的最低技能,因此我们要熟练的掌握遍历集合的方式。 在这里我们不讲for循环遍历,for循环无法对单

    2024年02月16日
    浏览(35)
  • Linux学习第二十二节-网卡IP设置

    1. 修改网卡IP地址 方式一:通过修改 网卡配置文件 修改 网卡配置文件位置: /etc/sysconfig/network-scripts/网卡名 #ifconfig   表示用于显示和设置网卡的参数 #ip addr   表示用于显示和设置网卡的参数   #systemctl restart network 表示重启网络 #ifup 网卡名 表示启动该网卡设备 #ifdown 网卡

    2024年02月17日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包