《深入理解C++11:C++11新特性解析与应用》笔记五
第五章 提高类型安全
5.1 强类型枚举
5.1.1 枚举:分门别类与数值的名字
具名枚举类型一般声明类似:enum Gender { Male, Female }。
匿名枚举类型可以使用三种方式实现:
第一种方式时宏,比如
#define Male 0
#define Female 1
宏的弱点在于其定义的知识预处理阶段的名字,会干扰正常代码。
第二种方式时匿名的enum,比如enum { Male, Female};
c++中更受推荐的是第三种方式,静态变量,例如const static int Male = 0;
静态变量能够得到编译时检查,作用域局限于文件内,但是会在目标代码中产生实际的数据,相比而言匿名的枚举似乎更好用。
5.1.2 有缺陷的枚举类型
c/c++的enum有个奇怪的设定,就是具名enum类型的名字和enum的成员的名字都是全局可见的。
上面例子中的两个General都是全局的名字,因此编译器会报错。解决的办法是将它们声明在不同的namespace之下,然后用限定namespace的方式去访问它。
另外,由于c中枚举被设计为常量数值的别名的本性,所以枚举的成员总是可以被隐式地转换为整型。很多时候这是不安全的。为解决这一问题,一般会对枚举类型进行封装。
但是封装过于复杂,封装采用静态成员,enum变成了非POD。传递参数的时候如果参数是结构体,就不能使用寄存器来传参,而整型可以通过寄存器传递。class封装版本的枚举作为函数参数传递,就会带来一定性能损失。
此外,枚举类型所占用的空间大小也是一个不确定的量。因为标准规定,c++枚举所基于的基础类型由编译器具体指定实现。
5.1.3 强类型枚举以及c++11对原有枚举类型的扩展
c++11引入一种新的枚举类型,即枚举类,又称强类型枚举。
声明强类型枚举只需在enum后面加上关键字class,比如:
enum class Type { General, Light, Medium, Heavy };
强类型枚举的几个优势:
1.强作用域,强类型枚举成员的名称不会被输出到其父作用域空间
2.转换限制,强类型枚举成员的值不可以与整型隐式地互相转换。
3.可以指定底层类型。默认底层类型为int,可以在枚举名称后面加上“: type”来显式指定底层类型,type可以试除wchar_t之外的任何整型。
c++11还对原来的枚举进行了扩展。首先底层的基本类型也可以跟强类型枚举一样,显式地由程序员指定。第二则是枚举成员的名字除了会自动输出到父作用域,也可以在枚举类型定义的作用域内有效。这两点都是向后兼容的。
此外在声明强类型枚举的时候,也可以使用enum struct关键字,两者没有任何区别。
匿名的enum class可能什么也做不了。
5.2 堆内存管理:只能指针与垃圾回收
5.2.1 显式内存管理
显式内存管理常见问题:
一野指针:内存单元已被释放,但是之前指向它的指针却还在被使用。
二重复释放。
三内存泄漏。
c++11新保准对智能指针进行了改进,还提供了所谓的最小垃圾回收的支持。
5.2.2 c++11的智能指针
c++98中智能指针通过一个模板类型“auto_ptr”来实现。auto_ptr以对象的方式管理堆分配的内存,并在适当的时间(比如析构),释放所获得的堆内存。这种堆内存管理的方式只需要程序员将new操作返回的指针作为auto_ptr的初始值即可,程序员不用再显式地调用delete。
auto_ptr存在一些缺点,譬如拷贝时候返回一个左值,不能调用delete[]等,所在在c++11标准中废弃了。c++11中改用unique_ptr, shared_ptr及weak_ptr等智能指针来自动回收堆分配的对象。
每个智能指针都重载了*运算符,可以用来访问所分配的堆内存。智能指针析构或者调用reset成员的时候,智能指针能释放其拥有的堆内存。
unique_ptr唯一拥有所指向的对象内存,仅能通过标准库的move函数来转移。unique_ptr是一个删除了拷贝构造函数、保留了移动构造函数的指针封装类型。
shared_ptr允许多个智能指针共享地拥有同一堆分配对象的内存,实现上采用了引用计数。shared_ptr调用reset成员函数只会引起引用计数的降低,而不会导致堆内存的释放。只有在引用计数归零的时候,shared_ptr才会真正释放所占有的堆内存的空间。
weak_ptr可以指向shared_ptr指针所指向的对象内存,却不拥有该内存。使用weak_ptr成员lock,可以返回其指向内存的一个shared_ptr对象,且在所指对象内存已经无效时,返回指针空值,可用于验证shared_ptr的有效性。
5.2.3 垃圾回收的分类
垃圾回收的方式主要分为两大类:
1.基于引用计数的垃圾回收器
优点是简单,不会造成程序暂停,也不会对系统缓存或者交换空间造成冲击。但是难以处理环形引用问题,产生的额外开销也不小。
2.基于跟踪处理的垃圾回收器
跟踪处理的垃圾回收处理机制更为广泛地应用。其基本方法是产生跟踪对象的关系图,然后进行垃圾回收。使用跟踪方式的垃圾回收算法主要有以下几种:
(1)标记清除(mark-sweep)
该算法将程序中正在使用的对象视为根对象,从根对象开始查找它们所引用的堆空间,并在这些堆空间上做标记。当标记结束后,所有被标记的对象就是可达对象(reachable object)或活对象(live Object),而没有被标记的对象就被认为是垃圾,在第二步的清扫阶段就会被回收掉。
这种方法的特点是活的对象不会被移动,但是其存在会出现大量的内存碎片的问题。
(2)标记整理(mark-compact)
该方法标记的方法和标记清除一样,但是标记完之后,不再遍历所有对象清扫垃圾了,而是将活的对象向左靠齐,这就解决了内存碎片的问题。
标记整理的方法有个特点就是移动活的对象,因此相应地,程序中所有对堆内存的引用都必须更新。
(3)标记拷贝(mark-copy)
该算法将堆空间分为两部分:from和to。刚开始系统只从from的堆空间里面分配内存,当from分配满的时候系统就开始垃圾回收:从from对空间里找出所有活的对象,拷贝到to的堆空间里。这样一来,from的堆空间里面就全剩下垃圾了。而对象被拷贝到to里之后,在to里是紧凑排列的。接下来是需要将from和to交换一下角色,接着从新的from里面开始分配。
标记拷贝算法的一个问题是堆的利用率只有一半,而且也需要移动活的对象。这种算法其实是标记整理的另一种实现而已。
5.2.4 c++与垃圾回收
指针的灵活对垃圾回收带来了很大的困扰。被隐藏的指针会导致编译器在分析指针可达性时出错。c++11解决这种问题的方法就是让程序员利用新的接口来提示编译器代码中存在着指针不安全的区域。
5.2.5 c++11与最小垃圾回收支持
c++11为了做到最小的垃圾回收支持,首先对安全的指针进行了定义,也就是c++11中所谓的安全派生(safely derived)的指针。安全派生的指针是指向由new分配的对象或其子对象的指针。安全派生指针的操作包括:
1.在解引用基础上的引用,比如:&*p。
2.定义明确的指针操作,比如:p+1。
3.定义明确的指针转换,比如static_cast<void *>(p)。
4.指针和整型之间的reinterpret_cast,比如reinterpret_cast<intptr_t>(p)。intptr_t是c++11中一个可选择实现的类型,其长度等于平台上指针的长度。
可通过get_pointer_safety函数查询编译器是否支持最小垃圾回收。
如果代码中出现了指针不安全使用的情况,可以通过一些API来通知垃圾回收器不得回收该内存。即需要声明该内存为可达到的:
declare_reachable()显式地通知垃圾回收器某一个对象应被认为可达到的,即使它的所有指针都对回收器不可见。undeclare_reachable()则可以取消这种可达声明。
declare_reachable只需要传入一个简单的void *指针,但undeclare_reachable通常被设计为一个函数模板。
有时候程序员会选择在一大片连续的堆内存上进行指针式操作,为了让垃圾回收器不关心该区域,也可以使用declare_no_pointers及undeclare_no_pointers函数来告诉垃圾回收器该内存区域不存在有效的指针。
5.2.6 垃圾回收的兼容性
必须限制指针的使用或者使用declare_reachable/undeclare_reachable、declare_no_pointers/undeclare_no_pointers来让一些不安全的指针使用免于垃圾回收器的检查。
此外c++标准对指针的垃圾回收支持仅限于系统提供的new操作符分配的内存,而malloc分配的内存则会被认为总是可达的。
更为现实的状况是本书写作时,垃圾回收特性还没有得到任何表一起的支持,即使是所谓的最小垃圾回收。
相关文章:

《深入理解C++11:C++11新特性解析与应用》笔记五
第五章 提高类型安全 5.1 强类型枚举 5.1.1 枚举:分门别类与数值的名字 具名枚举类型一般声明类似:enum Gender { Male, Female }。 匿名枚举类型可以使用三种方式实现: 第一种方式时宏,比如 #define Male 0 #define Femal…...

Y9000P + ubuntu22.04 配置Anaconda+pycharm +pytorch
Anaconda3 的安装及使用方法安装 Anaconda3 Anaconda3 是 Anaconda 的具体版本 Anaconda3 中的 Python 解释器默认使用的是 Python3.x 版本,而不是 Python2.x 版本 Python2.x 版本中,字符串是以 ASCII 编码处理的,而在 Python3.x 版本中&am…...
使用Ubuntu编译FFmpeg生成Android动态库/静态库
环境 我这里使用windows里的wsl2的ubuntu,使用物理机或者vmware,vbox之类的安装的ubuntu理论上也可以. gcc编译使用的环境如下: Ndk使用17 FFmpeg使用4.0.2. clang编译使用的环境如下: Ndk使用21.4 FFmpeg使用6.1 FFmpeg下载地址:https://ffmpeg.org/…...

【AIGC-图片生成视频系列-2】八仙过海,各显神通:AI生成视频相关汇总剖析
最近「图片生成视频系列」层出不穷,我拜读并结合实践(对,就是手撕代码,有开源就撕),并对以下几篇文章的相似点以及关键点稍微做个总结: 一. 生成视频中图像的一致性 在图像生成视频的这个过程…...

SpringBoot集成RabbitMq消息队列【附源码】
1. 项目背景 要啥项目背景,就是干!!! SpringBoot版本:2.7.12 2. Rabbit MQ安装 这里讲解使用docker安装RabbitMQ,如果在windows下面安装RabbitMQ,参考下文 【笑小枫的按步照搬系列】Window…...

MySQL数据库的安装与环境配置
下载 下载MySQL8 安装 解压 配置MySQL环境变量 系统环境变量path D:\ProgramFiles\mysql-8.0.20-winx64\bin 1.点击属性 2.点击高级系统设置 3.点击环境变量 4.在系统变量中找到path 注意这里不是用户变量 5.新建后输入解压的地址 MySQL初始化和启动 以管理员身份运行cmd…...

【广州华锐互动】VR科技科普展厅平台:快速、便捷地创建出属于自己的虚拟展馆
随着科技的不断进步,虚拟现实(VR)技术已经在许多领域取得了显著的成果。尤其是在展馆设计领域,VR科技科普展厅平台已经实现了许多令人瞩目的新突破。 VR科技科普展厅平台是广州华锐互动专门为企业和机构提供虚拟展馆设计和制作的在线平台。通过这个平台&…...

XML Extension Supplement
LEGAL ISSUES, COMPANY POLICIES AND STANDARDS Web Services A Web service is a software system designed to support interoperable machine-to-machine interaction over a network. URI和URL URI,全称是统一资源标识符(Uniform Resource Ident…...

手拉手Springboot获取yml配置文件信息
环境介绍 技术栈 springboot3 软件 版本 mysql 8 IDEA IntelliJ IDEA 2022.2.1 JDK 17 Spring Boot 3.1.7 配置文件说明:启动配置文件优先级:properties高于yml 配置文件application.yml yml是 JSON 的超集,简洁而强大…...

行人重识别(ReID)基础知识入门
这里写目录标题 1、ReID技术概述1.1 基本原理1.2 实现流程1.3 重识别存在的技术挑战 2、训练数据格式介绍 1、ReID技术概述 1.1 基本原理 ReID,全称Re-identification,目的是利用各种智能算法在图像数据库中找到与要搜索的目标相似的对象。ReID是图像检…...

【音视频 ffmpeg 学习】 跑示例程序 持续更新中
环境准备 在上一篇文章 把mux.c 拷贝到main.c 中 使用 attribute(unused) 消除警告 __attribute__(unused)/** Copyright (c) 2003 Fabrice Bellard** Permission is hereby granted, free of charge, to any person obtaining a copy* of this software and associated docu…...
前端axios与python库requests的区别
当涉及到发送HTTP请求时,Axios和Python中的requests库都是常用的工具。下面是它们的详细说明: Axios: Axios是一个基于Promise的HTTP客户端,主要用于浏览器和Node.js环境中发送HTTP请求。以下是Axios的一些特点和用法࿱…...
达梦数据库文档
1:达梦数据库(DM8)简介 达梦数据库管理系统是武汉达梦公司推出的具有完全自主知识产权的高性能数据库管理系统,简称DM。达梦数据库管理系统目前最新的版本是8.0版本,简称DM8。 DM8是达梦公司在总结DM系列产品研发与应用经验的基础上…...

CorelDRAW2024新功能有哪些?CorelDRAW2024最新版本更新怎么样?
CorelDRAW2024新功能有哪些?CorelDRAW2024最新版本更新怎么样?让我们带您详细了解! CorelDRAW Graphics Suite 是矢量制图行业的标杆软件,2024年全新版本为您带来多项新功能和优化改进。本次更新强调易用性,包括更强大…...

基于Mapify的在线艺术地图设计
地图是传递空间信息的有效载体,更加美观、生动的地图产品也是我们追求目标。 那么,我们如何才能制出如下图所示这样一幅艺术性较高的地图呢?今天我们来一探究竟吧! 按照惯例,现将网址给出: https://www.m…...

mxxWechatBot微信机器人V2版本文档说明
大家伙,我是雄雄,欢迎关注微信公众号:雄雄的小课堂。 先看这里 一、前言二、mxxWechatBot流程图三、怎么使用? 一、前言 经过不断地探索与研究,mxxWechatBot正式上线,届时全面开放使用。 mxxWechatBot&am…...

红队打靶练习:MISDIRECTION: 1
信息收集 1、arp ┌──(root㉿ru)-[~/kali] └─# arp-scan -l Interface: eth0, type: EN10MB, MAC: 00:0c:29:69:c7:bf, IPv4: 192.168.12.128 Starting arp-scan 1.10.0 with 256 hosts (https://github.com/royhills/arp-scan) 192.168.12.1 00:50:56:c0:00:08 …...

Jmeter吞吐量控制器总结
吞吐量控制器(Throughput Controller) 场景: 在同一个线程组里, 有10个并发, 7个做A业务, 3个做B业务,要模拟这种场景,可以通过吞吐量模拟器来实现。 添加吞吐量控制器 用法1: Percent Executions 在一个线程组内分别建立两个吞吐量控制器, 分别放业务A和业务B …...

【XML】TinyXML 详解(二):接口详解
【C】郭老二博文之:C目录 1、XML测试文件(laoer.xml) <?xml version"1.0" standalone"no" ?> <!-- Hello World !--> <root><child name"childName" id"1"><c_child…...

【机器学习】人工智能概述
人工智能(Artificial Intelligence,简称AI)是一门研究如何使机器能够像人一样思考、学习和执行任务的学科。它是计算机科学的一个重要分支,涉及机器学习、自然语言处理、计算机视觉等多个领域。 人工智能的概念最早可以追溯到20世…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...

让AI看见世界:MCP协议与服务器的工作原理
让AI看见世界:MCP协议与服务器的工作原理 MCP(Model Context Protocol)是一种创新的通信协议,旨在让大型语言模型能够安全、高效地与外部资源进行交互。在AI技术快速发展的今天,MCP正成为连接AI与现实世界的重要桥梁。…...
【学习笔记】深入理解Java虚拟机学习笔记——第4章 虚拟机性能监控,故障处理工具
第2章 虚拟机性能监控,故障处理工具 4.1 概述 略 4.2 基础故障处理工具 4.2.1 jps:虚拟机进程状况工具 命令:jps [options] [hostid] 功能:本地虚拟机进程显示进程ID(与ps相同),可同时显示主类&#x…...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...

Chromium 136 编译指南 Windows篇:depot_tools 配置与源码获取(二)
引言 工欲善其事,必先利其器。在完成了 Visual Studio 2022 和 Windows SDK 的安装后,我们即将接触到 Chromium 开发生态中最核心的工具——depot_tools。这个由 Google 精心打造的工具集,就像是连接开发者与 Chromium 庞大代码库的智能桥梁…...
深入理解Optional:处理空指针异常
1. 使用Optional处理可能为空的集合 在Java开发中,集合判空是一个常见但容易出错的场景。传统方式虽然可行,但存在一些潜在问题: // 传统判空方式 if (!CollectionUtils.isEmpty(userInfoList)) {for (UserInfo userInfo : userInfoList) {…...

jdbc查询mysql数据库时,出现id顺序错误的情况
我在repository中的查询语句如下所示,即传入一个List<intager>的数据,返回这些id的问题列表。但是由于数据库查询时ID列表的顺序与预期不一致,会导致返回的id是从小到大排列的,但我不希望这样。 Query("SELECT NEW com…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...