【C++】c++11新特性(一)

news2025/1/19 13:12:59

目录

{ }列表初始化

内置类型---对单值变量及数组的初始化

列表初始化时进行的类型转换

自定义类型---对类对象或结构的初始化

initializer_list

1. 定义接受 initializer_list 参数的构造函数

2. 在函数中使用 initializer_list 参数

3. 使用 initializer_list 与 vector 等容器

用于推断类型的关键字

auto  和  decltype

用于管理虚方法的说明符

final  和  override

final

1. 修饰类

2. 修饰虚函数

3. 修饰非虚成员函数

override


                                            


{ }列表初始化

内置类型---对单值变量及数组的初始化

下面是将花括号列表初始化用于单值变量的情形 . 如下代码:

可以看出 变量 num1 和 变量num2 都被初始化为6 ;因此,采用大括号这种初始化方式可使用等号(=),也可以省略不写

那如果花括号里我们什么都不写呢?那么它的值会是什么如下代码:

如上可看到花括号中如果什么都不写,这种情况下变量将被初始化为 0

将花括号列表初始化用于数组初始化的情形 ,数组在之前就可使用列表初始化,但c++11对列表初始化新增了一些功能。

      1. 初始化数组时可以省略等号(=);

      2. 在花括号内可以不包含任何东西,此时,所有元素都被初始化为0,这与单值变量初始化类似

如下代码:

此外,对列表初始化语法用于 new表达式中:

前两行只是申请了内存空间(即对于单个对象申请了一个int型大小的空间,对于多个对象申请了连续的4个大小的int型空间);后两行既申请了空间又对其进行了初始化。

列表初始化时进行的类型转换

c++11这种列表初始化常用于复杂的数据类型提供值列表,相较于c(内置类型)的初始化方式来说,c++11列表初始化对类型转换的要求更加严格。具体来说就是不允许把更宽的类型转换为窄的类型,比如:int-->char 不允许(当int的范围超出char时)。如下代码演示:

       通过上面的代码可以看到,162行是 c 风格的初始化,把一个int类型的值为3556(已超出char的范围)赋给char类型变量,编译器只给了警告:发生截断,但还是可以通过的;而使用c++11的大括号{}列表初始化编译器就会直接报错,是不能通过编译的。因此,使用列表初始化时要注意类型间的转换

说明:列表初始化是禁止大类型向小类型转换的,上面是单值对象,数组也是一样的

自定义类型---对类对象或结构的初始化

将花括号列表初始化用于类对象,但要提供与某个构造函数的参数列表匹配的内容,并用大括号括起来。

花括号列表初始化可以用于类对象(要隐式类型转换,调用构造函数),是该类要支持单参数或多参数的构造函数(可以是带缺省值的) ;

说明:当用于new表达式 (想要申请并初始化多个对象) 时,如果申请的 对象个数 与 大括号中 初始化的个数不符(小于),这时,剩余的个数会去调用默认的构造函数初始化,此时需要有默认构造函数才行,否则会有编译错误:如:上面代码中 289 行,就需要提供默认构造函数才行,要么就对象个数与大括号中初始化数一致。

将花括号列表初始化用于结构体的情形

initializer_list

initializer_list 是一个模板类,它允许使用花括号初始化器({})来初始化对象。initializer_list 通常用于构造函数和函数参数以接受任意数量的元素进行初始化

这提供了一种方便的方式来初始化容器、数组或其他集合类型。

下面是initializer_list 的用法

1. 定义接受 initializer_list 参数的构造函数

#include <iostream>
#include <vector>
#include <initializer_list>
using namespace std;

class MyClass 
{
public:
    MyClass(initializer_list<int> il) 
    {
        for (auto& e : il) 
        {
            data.push_back(e);
        }
    }

    void print()  
    {
        for (auto& e : v) 
        {
            cout << e << " ";
        }
        cout << endl;
    }

private:
    vector<int> v;
};

int main() 
{
    MyClass mc = { 1, 2, 3, 4, 5 }; // 使用花括号初始化  
    mc.print(); // 输出: 1 2 3 4 5  

    return 0;
}

2. 在函数中使用 initializer_list 参数

#include <iostream>
#include <initializer_list>
using namespace std;

void print_list(initializer_list<int> il) 
{
    for (auto& e : il) 
    {
        cout << e << " ";
    }
    cout << endl;
}

int main() 
{
    print_list({ 10, 20, 30, 40, 50 }); // 输出: 10 20 30 40 50  

    return 0;
}

  3. 使用 initializer_list 与 vector 等容器

vector和其他STL容器通常都有接受initializer_list参数的构造函数,因此,可以直接使用花括号初始化:

int main() 
{
    vector<int> v = { 1, 2, 3, 4, 5 };

    for (auto& e: v) 
    {
        cout << e << " ";
    }

    cout << endl; // 输出: 1 2 3 4 5  

    return 0;
}

说明:

        1.  initializer_list对象只用于初始化,它们不是真正的容器,不支持修改操作(如push_back

        2. 如果类有多个构造函数,并且其中一些接受单个参数,可能会遇到与隐式类型转换相关的歧义。此时,可能需要使用explicit关键字来防止不期望的隐式转换

initializer_list提供了一种方便且灵活的方式来初始化对象和集合,使得代码更加清晰和易读

用于推断类型的关键字

auto  和  decltype

关键字auto之前是一个存储类型的说明符,但c++11重新定义了auto的含义:将 其用于实现自动类型推断。要求必须进行显示初始化,让编译器将定义对象的类型设置为初 始化值的类型

关键字decltype, 把变量的类型声明为表达式指定的类型。

1. 若decltype 指定的表达式没有括号,则所声明变量的类型和指定表达式的类型相同

代码中所声明的变量的类型 z、u、w 与 decltype括号中所指定的类型一样

注意:虽然 m和n 都是引用,但表达式 m+n 不是引用,因此,mn 的类型是 int 而不是 int&

是两个int的和;

2. 若decltype 指定的表达式是函数调用,则所声明变量的类型函数返回值的类型相同

注意:编译器是通过查看函数的原型 确定返回类型,而不会实际调用函数

3. 若decltype 指定的表达式是一个左值且带有括号,则所声明变量的类型左值的引用

上面代码中,q 是被括号括起来的,则声明的变量 v 的类型是 左值 q 的引用,注意与无括号的对比;

注意:若用decltype 声明的变量 是上面代码中 323 行 的形式 就必须要引用一个左值,否则编译会报错;如:decltype((q))   v;  //erro

说明:括号并不会改变表达式的值 和 左值性

用于管理虚方法的说明符

final  和  override

final

final 可用于修饰类、虚函数final 关键字主要用于那些设计为不应该被继承或不应该被重写的类和方法。使用final 可以增强代码的可读性和可维护性,因为它明确指出了哪些类和方法是封闭的,不应该被修改或扩展。同时,它也有助于防止由于错误地继承或重写而引起的潜在问题

下面是final的几种用法

1. 修饰类

final用于类时,表示这个类不能被继承。这有助于防止不希望被继承的类被意外地继承

class Base final 
{
    // ... 类成员 ...  
};

// 下面的代码会编译错误,因为Base类被声明为final  
class Derived : public Base 
{
    // ... 类成员 ...  
};
2. 修饰虚函数

当 final 用于虚函数时,表示这个虚函数在派生类中不能被重写。这有助于确保某些关键的函数行为在类的继承体系中保持不变

class Base {
public:
    virtual void func() final 
    {
        // ... 函数的实现  
    }
    // ... 其他成员 ...  
};

class Derived : public Base {
public:
    // 下面的代码会编译错误,由于 func()函数在Base类中被声明为final  
    void func()  // ... 想要重写的函数实现 ... 
    {
        // ... 函数的实现
    }
};
3. 修饰非虚成员函数

虽然非虚成员函数也可以使用final关键字,但这通常没有太多实际意义,因为非虚成员函数本来就不能被重写。

override

  override关键字用于显式地指示一个成员函数在派生类中重写了基类中的虚函数。使用override的好处在于,它提供了编译时的检查,确保你确实重写了基类中的某个虚函数。如果基类中没有相应的虚函数,编译器会报错,从而防止潜在的错误。

下面是override的用法:   

class Base {
public:
    virtual void func1() 
    {
        // 基类虚函数的实现  
    }

    // 非虚函数,不能被重写  
    void func2()
    {
        // ...  
    }
};

class Derived : public Base {
public:
    // 使用override关键字显式地表示我们重写了Base类的func1函数,
    // 也可以不使用override,但使用override可以提供额外的检查  
    void func1() override
    {
        // 派生类重写func1函数的实现  
    }

    // 尝试重写Base类的func2函数,但由于func2不是虚函数,这里会编译错误  
    // 即使使用了override关键字,也无法将其变为虚函数  
    void func2() override
    {
        // 尝试重写的实现,但会导致编译错误  
    }
};

在上面的演示中,Derived类继承了Base类,并重写了func1这个虚函数。通过在派生类的成员函数声明后添加override关键字,告诉编译器这个函数是重写的,并且编译器会检查基类中是否存在相应的虚函数。如果基类中没有相应的虚函数,编译器将报错。

注意:

       即使不使用override关键字,只要函数签名(包括返回类型和参数列表)与基类中的虚函数匹配,派生类中的成员函数也会被视为重写了基类的虚函数。但是,使用override提供了额外的安全性,因为它强制要求基类中存在一个可重写的虚函数。

只有虚函数才能被重写。如果尝试重写非虚函数,即使使用了override关键字,也会导致编译错误


      

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

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

相关文章

C#将Console写至文件,且文件固定最大长度

参考文章 将C#的Console.Write同步到控制台和log文件输出 业务需求 在生产环境中&#xff0c;控制台窗口不便展示出来。 为了在生产环境中&#xff0c;完整记录控制台应用的输出&#xff0c;选择将其输出到文件中。 但是&#xff0c;一次性存储所有输出的话&#xff0c;文件会…

基于SSM+Jsp+Mysql的二手车交易网站

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

5G智慧地铁数字孪生可视化平台,推进铁路行业数字化转型

随着科技的快速发展&#xff0c;5G智慧地铁数字孪生可视化平台正逐渐成为铁路行业数字化转型的重要推动力。巨蟹数科数字孪生平台集成了5G通信技术、大数据分析、云计算和人工智能等先进技术&#xff0c;通过构建数字孪生模型&#xff0c;实现对地铁运营全过程的实时监控、预测…

【智能排班系统】基于SpringSecurity实现登录验证、权限验证

文章目录 SpringSecurity介绍sss-security实现依赖工具类Jwt工具JSON响应工具加密工具类 用户上下文用户信息实体类用户上下文 自定义重写自定义无权限的报错自定义密码加密自定义用户类 过滤器登录过滤器权限过滤器 Service登录Service 配置类说明登录验证权限验证IP流量限制 …

JDK安全剖析之安全处理入门

0.前言 Java 安全包括大量 API、工具以及常用安全算法、机制和协议的实现。Java 安全 API 涵盖了广泛的领域&#xff0c;包括加密、公钥基础设施、安全通信、身份验证和访问控制。Java 安全技术为开发人员提供了编写应用程序的全面安全框架&#xff0c;还为用户或管理员提供了…

蓝桥集训之斐波那契数列

蓝桥集训之斐波那契数列 核心思想&#xff1a;矩阵乘法 将原本O(n)的递推算法优化为O(log2n) 构造1x2矩阵f和2x2矩阵a 发现f(n1) f(n) * a 则f(n1) f(1) * an可以用快速幂优化 #include <iostream>#include <cstring>#include <algorithm>using na…

跨站请求伪造漏洞(CSRF)

什么是CSRF CSRF&#xff08;Cross-Site Request Forgery&#xff09;&#xff0c;也被称为 one-click attack 或者 session riding&#xff0c;即跨站请求伪造攻击。 漏洞原理 跨站请求伪造漏洞的原理主要是利用了网站对用户请求的验证不严谨。攻击者会在恶意网站中构造一个…

RAG知识分享

文章目录 博客详细讲解视频点击查看高清脑图 1.为什么要做RAG1.1. 解决幻觉问题1.1.1 直接输入问题1.1.2. 问题 相关知识 2. 什么是RAG2.1. 基本概念2.2. 基本RAG方法2.2.1. 知识预处理2.2.2. 知识检索2.2.3. 答案生成 3. RAG 与 Long Context3.1. Long Context3.2. RAG 与Lon…

你为什么选择程序员这个职业?

注意&#xff0c;今天的这篇文章&#xff0c;我只是对程序员这份工作所需要面对的问题挑选一些有意思的话题讲讲我的理解&#xff0c;并不是对程序员的职业规划进行分享。本文分为入行前和入行后两个部分&#xff0c;分别聊聊。 入行前 所谓入行前&#xff0c;其实就是指还是学…

力扣面试150: O(1) 时间插入、删除和获取随机元素 HashMap结合数组

Problem: 380. O(1) 时间插入、删除和获取随机元素 文章目录 思路复杂度Code 思路 &#x1f469;‍&#x1f3eb; 三叶题解 复杂度 时间复杂度: O ( 1 ) O(1) O(1) 空间复杂度: O ( n ) O(n) O(n) Code class RandomizedSet {static int[] nums new int[200_010];//存…

RabbitMQ小记

参考书籍&#xff1a;朱忠华的《RabbitMQ实战指南》 一、基础概念 1.Exchange 1.1 创建方法的参数&#xff0c;exchangeDeclare() exchange&#xff1a;交换器的名称type&#xff1a;交换器的类型durable&#xff1a;是否持久化&#xff0c;true代表持久化。&#xff08;持…

iperf图形化打流工具JPerf2.0使用教程(1):相关设置介绍

0 前言 iperf是一个很常用的网络性能测试工具&#xff0c;经常来进行打流测试&#xff0c;用来查看丢包率、抖动时间等网络通信情况&#xff0c;但它是使用命令行操作的&#xff0c;使用起来不太友好。本文介绍基于iperf的图形化操作工具JPerf2.0。 1 JPerf2.0的客户端和服务…

蓝桥杯速成5-AD/DA模数转换

一、原理图 上图可知该芯片使用的是iic时序&#xff0c;而不是51单片机的xpt2046时序&#xff0c;iic我们都很熟悉了吧 并且大赛还提供了我们iic底层驱动代码 左上角有AIN0-4四个转换输入通道&#xff0c;和AOUT一个输出通道&#xff0c;由控制字节选择 地址字节&#xff1a;0x…

Stable Diffusion本地部署教程

Stable Diffusion本地部署的步骤一般包括准备环境、下载Stable Diffusion模型和依赖库、配置运行参数等。下面是一个通用的教程&#xff0c;用以在计算机上本地部署Stable Diffusion。 准备环境 1. 确保硬件满足最低要求&#xff1a; - 一块NVIDIA GPU&#xff0c;至少4GB…

LLMOps快速入门,轻松开发部署大语言模型

大家好&#xff0c;如今我们能够与ChatGPT进行轻松互动&#xff1a;只需输入提示&#xff0c;按下回车&#xff0c;就能迅速得到回应。然而&#xff0c;这个无缝互动的底层&#xff0c;是一系列复杂而有序的自动执行步骤&#xff0c;即大型语言模型运营&#xff08;LLMOps&…

【数据分析面试】11. 计算账户关闭率(SQL:评估不同查询方法的性能效率)

题目 给定一个账户状态表&#xff0c;编写一个查询以获取在2019年12月31日活跃并在2020年1月1日关闭的账户所占的百分比&#xff0c;以及在2019年12月31日活跃的总账户数。每个账户只有一条每日记录&#xff0c;显示其在当天结束时的状态。 注意&#xff1a;将结果四舍五入到…

在同一个局域网如何共享打印机和文件

1.在连接了打印机的主机上设置 1.1启用windows共享 打开网络与共享中心&#xff0c;点击“更改高级共享设置” 选择&#xff1a; “启用网络发现”“启用文件和打印机共享”“启用共享以便可以访问网络的用户可以读取和写入公用文件夹中的文件” 打开控制面板&#xff0c;选…

STM32-02基于HAL库(CubeMX+MDK+Proteus)GPIO输出案例(LED流水灯)

文章目录 一、功能需求分析二、Proteus绘制电路原理图三、STMCubeMX 配置引脚及模式&#xff0c;生成代码四、MDK打开生成项目&#xff0c;编写HAL库的GPIO输出代码五、运行仿真程序&#xff0c;调试代码 一、功能需求分析 在完成开发环境搭建之后&#xff0c;开始使用STM32GP…

python标准数据类型--列表常用方法

在Python中&#xff0c;列表&#xff08;List&#xff09;是一种非常常用的数据类型&#xff0c;用于存储一组有序的元素。Python提供了许多内置方法来操作列表&#xff0c;使得对列表的处理变得非常灵活和便捷。在本篇博客中&#xff0c;我们将介绍一些常用的列表方法&#xf…

Python | Leetcode Python题解之第8题字符串转换整数atoi

题目&#xff1a; 题解&#xff1a; INT_MAX 2 ** 31 - 1 INT_MIN -2 ** 31class Automaton:def __init__(self):self.state startself.sign 1self.ans 0self.table {start: [start, signed, in_number, end],signed: [end, end, in_number, end],in_number: [end, end,…