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

目录

{ }列表初始化

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

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

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

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关键字,也会导致编译错误


      

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

教你网络安全

如今&#xff0c;组织的信息系统和数据面临着许多威胁。而人们了解网络安全的所有基本要素是应对这些威胁的第一步。 网络安全是确保信息完整性、机密性和可用性(ICA)的做法。它代表了应对硬盘故障、断电事故&#xff0c;以及来自黑客或竞争对手攻击等防御和恢复能力。而后者包…

Android14应用启动流程(源码+Trace)

1.简介 应用启动过程快的都不需要一秒钟&#xff0c;但这整个过程的执行是比较复杂的&#xff0c;无论是对手机厂商、应用开发来说启动速度也是核心用户体验指标之一&#xff0c;本文采用Android14源码与perfetto工具进行解析。 源码参考地址&#xff1a;Search trace分析工…

基于单片机多功能MP3播放器系统设计

**单片机设计介绍&#xff0c;基于单片机多功能MP3播放器系统设计 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于单片机多功能MP3播放器系统设计是一个结合了硬件和软件设计的复杂项目。以下是对该系统设计的概要描述&#…

初识二叉树和二叉树的基本操作

目录 一、树 1.什么是树 2. 与树相关的概念 二、二叉树 1.什么是二叉树 2.二叉树特点 3.满二叉树与完全二叉树 4.二叉树性质 相关题目&#xff1a; 5.二叉树的存储 6.二叉树的遍历和基本操作 二叉树的遍历 二叉树的基本操作 一、树 1.什么是树 子树是不相交的;…

Github 2024-04-06Rust开源项目日报Top10

根据Github Trendings的统计,今日(2024-04-06统计)共有10个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Rust项目10HTML项目1Dart项目1RustDesk: 用Rust编写的开源远程桌面软件 创建周期:1218 天开发语言:Rust, Dart协议类型:GNU Affero General …

docker + miniconda + python 环境安装与迁移(详细版)

本文主要列出从安装dockerpython环境到迁移环境的整体步骤。windows与linux之间进行测试。 简化版可以参考&#xff1a;docker miniconda python 环境安装与迁移&#xff08;简化版&#xff09;-CSDN博客 目录 一、docker 安装和测试 二、docker中拉取miniconda&#xff…

C语言--指针终章

目录 1. sizeof和strlen的对⽐ 1.1 sizeof 1.2 strlen 1.3 sizeof 和 strlen的对⽐ 2. 数组和指针的理解——题目理解 2.1.sizeof 代码1&#xff1a; 代码2&#xff1a; 代码3&#xff1a; 代码4&#xff1a; 代码5&#xff08;二维数组&#xff09;&#xff1a; 2.2…

【蓝桥杯-单链表-网络寻路】

蓝桥杯-单链表-网络寻路 单链表基本操作操作一&#xff1a;向链表头插入一个数操作二:在第 k个插入的数后插入一个数操作三&#xff1a;删除第 k个插入的数后面的一个数&#xff1b; P8605 [蓝桥杯 2013 国 AC] 网络寻路 单链表基本操作 初始化有关操作 // head 表示头结点的…

Debian12 使用 nginx 与 php8.2 使用 Nextcloud

最近将小服务器升级了下系统&#xff0c;使用了 debian12 的版本&#xff0c;正好试试 nginx 和 php-fpm 这种方式运行 Nextcloud 这个私有云的配置。 一、基本系统及应用安装 系统&#xff1a;debian12 x86_64 位版本最小安装&#xff0c;安装后可根据自己需求安装一些工具&…

如何优化TCP?TCP的可靠传输机制是什么?

在网络世界中&#xff0c;传输层协议扮演着至关重要的角色&#xff0c;特别是TCP协议&#xff0c;以其可靠的数据传输特性而广受青睐。然而&#xff0c;随着网络的发展和数据量的激增&#xff0c;传统的TCP协议在效率方面遭遇了挑战。小编将深入分析TCP的可靠性传输机制&#x…

【C++初阶】 vector 在OJ中的使用

前言&#xff1a; &#x1f3af;个人博客&#xff1a;Dream_Chaser &#x1f388;博客专栏&#xff1a;C &#x1f4da;本篇内容&#xff1a;只出现一次的数字 和 杨辉三角 OJ 目录 一、只出现一次的数字 题目描述&#xff1a; 二、杨辉三角OJ 题目描述&#xff1a; 一、只…

vue快速入门(七)内联语句

注释很详细&#xff0c;直接上代码 上一篇 新增内容 button点击事件绑定内联语句写法与要求 源码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-wid…

phpstorm设置头部注释和自定义注释内容

先说设置位置&#xff1a; PhpStorm中文件、类、函数等注释的设置在&#xff1a;setting-》Editor-》FIle and Code Template-》Includes-》PHP Function Doc Comment下设置即可&#xff0c;其中方法的默认是这样的&#xff1a; /** ${PARAM_DOC} #if (${TYPE_HINT} ! "…

【第九篇】使用BurpSuite进行编码与解码

Burp存在一个功能&#xff0c;可以识别包含不透明数据&#xff08;例如会话令牌&#xff09;的消息。 如图&#xff1a;如果 Burp 识别所选内容的编码格式&#xff0c;它会自动解码数据。解码后的文本显示在 Inspector面板中。 在编码工具模块中&#xff0c;可对数据进行重复解…

C. MEX Game 1

本题如果我们去模拟这个算法的话会很麻烦&#xff0c;也会TLE&#xff0c;首先我们想 1&#xff0c;对于alice来说&#xff0c;先取小的&#xff0c;对于bob来说先删除alic想取的下一个小的 2&#xff0c;那如果这个数多于两个&#xff0c;那也就是说&#xff0c;alice肯定能…

电工技术学习笔记——正弦交流电路

一、正弦交流电路 1. 正弦量的向量表示法 向量表示方法&#xff1a;正弦交流电路中&#xff0c;相量表示法是一种常用的方法&#xff0c;用于描述电压、电流及其相位关系。相量表示法将正弦交流信号表示为复数&#xff0c;通过复数的运算来描述电路中各种参数的相互关系 …

C/C++预处理过程

目录 前言&#xff1a; 1. 预定义符号 2. #define定义常量 3. #define定义宏 4. 带有副作用的宏参数 5. 宏替换的规则 6. 宏和函数的对比 7. #和## 8. 命名约定 9. #undef 10. 命令行定义 11. 条件编译 12. 头文件的包含 13. 其他预处理指令 总结&#x…

IP地址:是给主机配置的,还是给网卡配置的?

在探索网络的奥秘时&#xff0c;我们经常会遇到一个看似简单但又复杂的问题&#xff1a;IP地址到底是配置在主机上&#xff0c;还是配置在网卡上&#xff1f;为什么我们通常说的是“主机IP地址”呢&#xff1f;让我们一起深入探讨。 1. 网卡与IP地址 &#x1f5a5;️&#x1f…

有同学和我说,深度学习不用特征工程,只有浅层机器学习方法采用特征工程,我说你误会了,我给你好好解释吧!!

1. 通俗解释 浅层机器学习算法&#xff08;如逻辑回归、决策树、支持向量机等&#xff09;和深度学习算法&#xff08;如神经网络&#xff09;在特征工程上的依赖性确实存在一些差异。 浅层机器学习算法的特征工程依赖性&#xff1a; 浅层算法通常需要手工选择和设计特征&…

lua学习笔记5(分支结构和循环的学习)

print("*****************分支结构和循环的学习******************") print("*****************if else语句******************") --if 条件 then end a660 b670 --单分支 if a<b thenprint(a) end --双分支 if a>b thenprint("满足条件")…