《深入理解C++11:C++11新特性解析与应用》笔记七

news2025/1/27 13:06:59

第七章 为改变思考方式而改变

7.1 指针空值--nullptr

7.1.1 指针空值:从0到NULL,再到nullptr

传统C头文件里NULL是一个宏定义:

在函数重载同时出现int和char *参数版本的函数时,使用NULL作为参数调用函数会调用int参数版本,而不是我们想要的char*参数版本。 引起该问的元凶是字面常量0的二义性,既可以是一个整型,也可以是一个无类型指针void*。除非对字面常量0进行强制类型转换b=并调用,否则编译器总是会优先把0看作是一个整型常量。

c++出于兼容性考虑,并没有消除字面常量0的二义性。但是引入了作为指针空值类型的常量nullptr,指针空值类型被命名为nullptr_t。nullptr是关键字,nullptr是有类型的,只能被隐式转化为指针类型,所以nullptr做参数可以成功调用char*版本的函数。

7.1.2 nullptr和nullptr_t

c++11标准不仅定义了指针空值常量nullptr,也定义了其指针空值类型nullptr_t。c++11标准严格规定了数据间的关系:

1.所有定义为nullptr_t类型的数据都是等价的,行为也是完全一致的。

2.nullptr_t类型数据可以隐式转换成任意一个指针类型。

3.nullptr_t类型数据不能转换为非指针类型。

4.nullptr_t类型数据不适用于算术运算表达式。

5.nullptr_t类型数据可以用于关系运算表达式,但仅能与nullptr_t类型数据或者指针类型数据进行比较,当且仅当关系运算符为==、<=、>=等时返回true。

7.1.3 一些关于nullptr规则的讨论

nullptr类型数据所占用的内存空间大小跟void*相同。

nullptr到任何指针的转换是隐式的,而(void*)0则必须经过类型转换后才能使用。

nullptr_t对象的地址可以被用户使用。虽然nullptr也是一个nullptr_t的对象,但它被定义为一个右值常量,因此用户不能获得nullptr的地址。

7.2 默认函数的控制

7.2.1 类与默认函数

在c++中声明自定义的类,编译器会默认生成一些被称为默认函数的成员函数,包括:

构造函数、拷贝构造函数、拷贝赋值函数(operator=)、移动构造函数、移动拷贝函数、析构函数。

c++编译器还会为以下这些自定义类型提供全局默认操作符函数:

operator ,,operator &,operator &&,operator *,operator ->,operator ->*,operator new,operator delete。

一旦实现了这些函数的自定义版本,则编译器不会再为该类自动生成默认版本。声明了带参的构造函数版本,必须声明不带参版本以完成无参的变量初始化。声明了自定义版本的构造函数,有可能导致自定义类型不再是POD的。

C++11中,可以在默认函数定义或者声明时加上"= default"来显式地指示编译器生成该函数的默认版本。另一方面,有时候又希望可以限制一些默认函数的生成,譬如有时候需要禁止使用拷贝构造函数,c++11中,可以在默认函数定义或者声明时加上“= delete”来显式地指示编译器不生成函数的缺省版本。

7.2.2 “= default”与“= deleted”

c++11中,也可以在类定义外显式指定缺省版本,这样可以对一个class定义提供多个实现版本,通过选择性编译,从而在提供缺省函数和自定义版本间切换。

c++11并不要求编译器为“operator ==”之类的函数提供缺省实现,但是将其声明为显式缺省的话,编译器会按照某些标准行为为其生成所需的版本。

显式删除可以避免用户使用一些不应该使用的类的成员函数,也可以避免编译器做一些不必要的隐式数据类型转换,例如:

隐式删除不应该和explicit同用。在下面的例子中:

显式删除导致显式构造的cc变量编译出错,但是Func调用中,编译器会尝试隐式地将char转为int,从而调用一次ConvType(int)构造函数,因而能通过编译。

显式删除并不局限于缺省版本的类成员函数或者全局函数上,对于普通函数,依然可以通过显式删除来禁止类型转换。

7.3 lambda函数

7.3.1 lambda的一些历史

7.3.2 c++11中的lambda函数

lambda函数的语法定义:

捕捉列表由多个捕捉项组成,以逗号分割,有如下形式:

[var]表示值传递方式捕捉变量var,[=]表示值传递方式捕捉所有父作用域的变量,[&var]表示引用传递捕捉变量var。[&]表示引用捕捉所有父作用域的变量。[this]表示值传递方式捕捉当前this指针。还可以进行组合,例如[=,&a,&b]表示引用传递方式捕捉a和b,其他变量以值传递方式捕捉。

默认情况下lambda函数总是一个const函数,mutable可以取消其常量性,使用时参数列表不可省略。

不需要返回值的时候也可以连同符号->一起省略。

c++11标准规定在块作用域以外的lambda函数捕捉列表必须为空,而在块作用域中的lambda函数仅能捕捉父作用域中的自动变量。

7.3.3 lambda与仿函数

在c++11之前,我们在STL中会用到一种特别的对象,称之为函数对象,或者仿函数functor,也就是重定义了成员函数operator()的一种自定义类型对象。在使用它的时候,在代码层面跟函数的使用一样,但本质却是一种对象。仿函数是编译器实现lambda的一种方式。现阶段,通常编译器会把lambda函数转化为一个仿函数对象。

7.3.4 lambda的基础使用

lambda可用于实现局部函数。

7.3.5 关于lambda的一些问题及有趣的实验

如果需要捕捉的值称为lambda函数的常量,通常需要使用按值传递的方式捕捉。反之,需要捕捉的值称为lambda函数运行时的变量,则应采用按引用方式进行捕捉。

lambda的类型并非简单的函数指针或者自定义类型,lambda的类型被定义为闭包的类,每个lambda表达式会产生一个闭包类型的临时对象(右值)。不过c++标准允许lambda表达式向函数指针的转换,前提是函数没有捕捉任何变量,且函数指针所示的函数原型,必须跟lambda函数有这相同的调用方式。

lambda函数的常量性及mutable关键字。现有c++11标准中lambda等价的是有常量成员函数operator()的仿函数,捕捉列表中的变量都会成为等价仿函数的成员变量,而常量成员函数中改变其值是不允许的,因而在按值捕捉的变量在没有声明为mutable的lambda函数中改变其会导致编译器报错。可以通过mutable修饰符消除其常量性,不过更推荐使用引用捕捉。

7.3.6 lambda与STL

当循环次数较多时,内联的lambda函数比函数指针性能好。函数指针应用范围相对狭小,特别是需要具备一些运行时才能决定的状态时,以前或许会使用仿函数,现在则可以选用lambda。

7.3.7 更多的一些关于lambda的讨论

在现有c++11中,lambda不是仿函数的完全替代者,这点很大程度上是由lambda的捕捉列表的限制造成的。仿函数可以被定义以后在不同的作用域范围内取得初始值,这使得仿函数天生具有跨作用域共享的特征。lambda函数被设计的目的,就是要就地书写,就地使用。

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

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

相关文章

机器学习部分相关概念

数据集(Data Set)即数据的集合&#xff0c;每一条单独的数据被称为样本(Sample)。 对于每个样本&#xff0c;它通常具有一些属性(Attribute)或者特征(Feature)&#xff0c; 特征所具体取得值被称为特征值(Feature Value)。 西瓜数据集 色泽根蒂纹理青绿稍蜷模糊乌黑蜷缩清晰 …

大数据 - 大数据入门第一篇 | 关于大数据你了解多少?

&#x1f436;1.1 概述 大数据&#xff08;BigData):指无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合&#xff0c;是需要新处理模式才能具有更强的决策力、洞察发现力和流程优化能力的海量、高增长率和多样化的信息资产。 大数据主要解决、海量数据的采…

【Linux】内核编译 镜像制作

文章目录 一、Ubuntu内核编译1.1 为什么自己编译内核1.2 Ubuntu 内核源码下载1.21 内核的作用1.22 Linux内核与ubuntu内核1.23 Ubuntu内核源码获取 1.3 在Windows系统下编译ubuntu内核1.4 在Linux系统下编译ubuntu内核 二、镜像制作 一、Ubuntu内核编译 1.1 为什么自己编译内核…

《QDebug 2023年12月》

一、Qt Widgets 问题交流 1. 二、Qt Quick 问题交流 1.Q_REVISION 标记的信号槽或者 REVISION 标记的属性&#xff0c;在子类中访问 Q_REVISION 是 Qt 用来做版本控制的一个宏。以 QQuickWindow 为例&#xff0c;继承后去访问 REVISION 标记的 opacity 属性或者 Q_REVISION…

nodejs+vue+微信小程序+python+PHP的林业信息管理系统的设计与实现-计算机毕业设计推荐

本文先充分调查林业信息管理系统的需求分析&#xff0c;深入剖析系统应该具有的功能&#xff0c;并设计完善的数据库。利用成熟的开发技术完成编码工作&#xff0c;林业信息管理系统可以为林业局领导提供业务管理功能&#xff0c;林业局领导也就是系统的管理员&#xff0c;具有…

【LeetCode】每日一题 2023_12_31 一年中的第几天(日期)

文章目录 随便聊聊时间题目&#xff1a;一年中的第几天题目描述代码与解题思路 随便聊聊时间 LeetCode&#xff1f;启动&#xff01;&#xff01;&#xff01; 12 月的打卡勋章&#xff0c;get&#xff01; 题目&#xff1a;一年中的第几天 题目链接&#xff1a;1154. 一年中…

数据结构期末复习(1)数据结构和算法 线性表

数据结构期末总复习&#xff08;gaois课堂版&#xff09; 数据结构的概念 数据结构是计算机科学中的一个重要概念&#xff0c;它指的是组织和存储数据的方式。数据结构可以帮助我们高效地操作和管理数据&#xff0c;使得计算机程序能够更加有效地执行各种任务。 数据结构有很…

【JavaScript】面向对象继承

目录 一、前言二、问题是最好的老师1、为什么要使用继承2、如何实现继承 三、面向对象继承方式1、借用构造函数继承1&#xff09;、优点2&#xff09;、缺点 2、原型链继承1&#xff09;、完整代码2&#xff09;、缺点 3、组合继承&#xff08;原型链借用构造函数&#xff09;1…

Rust学习笔记000 安装

安装命令 curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh $ curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh info: downloading installerWelcome to Rust!This will download and install the official compiler for the Rust programming la…

C语言转WebAssembly的全流程,及Web端调用测试

第一步&#xff1a;安装环境 参考网址&#xff1a;https://emscripten.org/docs/getting_started/downloads.html 具体过程&#xff1a; 克隆代码&#xff1a;git clone https://github.com/emscripten-core/emsdk.git进入代码目录&#xff1a;cd emsdk获取最新远端代码&…

关键字:try-catch关键字

在 Java 中&#xff0c;try-catch关键字用于异常处理。它们允许编写代码来捕获和处理异常&#xff0c;以确保程序能够在出现问题时合理地处理它们而不会崩溃。 以下是try-catch关键字的基本语法&#xff1a; 在try块中编写可能会抛出异常的代码。如果在try块中的任何代码抛出…

【Proteus仿真】【STM32单片机】自动除湿器系统

文章目录 一、功能简介二、软件设计三、实验现象联系作者 一、功能简介 本项目使用Proteus8仿真STM32单片机控制器&#xff0c;使用按键、LCD1602液晶、DHT11温湿度、继电器除湿模块等。 主要功能&#xff1a; 系统运行后&#xff0c;LCD1602显示DHT11传感器检测的湿度值阈值…

将数据“0x0f“写入AT24C02再读出送P1口显示

#include <reg51.h> // 包含51单片机寄存器定义的头文件 #include <intrins.h> //包含_nop_()函数定义的头文件 #define OP_READ 0xa1 // 器件地址以及读取操作,0xa1即为1010 0001B #define OP_WRITE 0xa0 // 器件地址以及写入…

浅析xxl-obj分布式任务调度平台RCE漏洞

文章目录 前言本地环境搭建1、初始化数据库2、搭建调度中心3、搭建出执行器 XXL-JOB漏洞1、后台弱口令->RCE2、未授权API->RCE3、默认accessToken4、CVE-2022-361575、SSRF漏洞->RCE 总结 前言 在日常开发中&#xff0c;经常会用定时任务执行某些不紧急又非常重要的事…

jmeter的常用功能及在测试中的基本使用和压测实战

Jmeter基础功能 了解Jmeter的常用组件 元件&#xff1a;多个类似功能组件的容器&#xff08;类似于类&#xff09; 一&#xff1a;Test Plan&#xff08;测试计划&#xff09; 测试计划通常用来给测试的项目重命名&#xff0c;使用多线程脚本运行时还可以配置线程组运行方式…

【HR非技术问题面试篇】你怎么看待加班?

你对加班怎么看待? &#x1f60a;老油条经典回答系列 &#x1f60a;老油条经典回答系列 这种问题&#xff0c;怎么回答都可以&#xff0c;我觉得重要的实时表达你自己。如果你就不想加班&#xff0c;也没必要勉强说自己爱加班&#xff0c;结果入职之后干的不开心。 不过&…

S32K312使用ITCM向FLASH代码区写入数据

使用C40_IP的系列方法向FLASH代码区写入数据时&#xff0c;程序会卡死在读取写操作的状态C40_Ip_MainInterfaceWriteStatus()这个方法中。本文主要介绍S32K312通过ITCM的方式&#xff0c;通过C40_IP的方法向FLASH代码区成功写入数据的方法和步骤。 首先&#xff0c;验证一下C4…

configparser.NoSectionError: No section: ‘***‘解决方案

大家好,我是水滴~~ 本文主要介绍 configparser.NoSectionError: No section: *** 问题的解决方案,希望能对你有所帮助。 《Python入门核心技术》专栏总目录・点这里 文章目录 1.问题描述2.解决方案3. INI 文件介绍1.问题描述 我们在使用 Python 的配置文件的时候,经常会看…

软件有效找不到dll文件,五种可靠的解决dll方法分享

电脑已经成为我们生活和工作中不可或缺的工具。然而&#xff0c;由于各种原因&#xff0c;电脑可能会出现一些问题&#xff0c;其中之一就是“电脑提示dll文件缺失”。这个问题可能会给我们的生活和工作带来很大的困扰&#xff0c;因此&#xff0c;我希望通过分享我的心得体会&…

005、数据类型

1. 关于数据类型 Rust中&#xff0c;每个值都有其特定的数据类型&#xff0c;Rust会根据数据的类型来决定如何处理它们。 Rust是一门静态类型语言&#xff0c;它在编译程序的过程中就需要知道所有变量的具体类型。在大部分情况下&#xff0c;编译器可以根据我们如何绑定、使用变…