当前位置: 首页 > news >正文

《深入理解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 枚举&#xff1a;分门别类与数值的名字 具名枚举类型一般声明类似&#xff1a;enum Gender { Male, Female }。 匿名枚举类型可以使用三种方式实现&#xff1a; 第一种方式时宏&#xff0c;比如 #define Male 0 #define Femal…...

Y9000P + ubuntu22.04 配置Anaconda+pycharm +pytorch

Anaconda3 的安装及使用方法安装 Anaconda3 Anaconda3 是 Anaconda 的具体版本 Anaconda3 中的 Python 解释器默认使用的是 Python3.x 版本&#xff0c;而不是 Python2.x 版本 Python2.x 版本中&#xff0c;字符串是以 ASCII 编码处理的&#xff0c;而在 Python3.x 版本中&am…...

使用Ubuntu编译FFmpeg生成Android动态库/静态库

环境 我这里使用windows里的wsl2的ubuntu&#xff0c;使用物理机或者vmware&#xff0c;vbox之类的安装的ubuntu理论上也可以. gcc编译使用的环境如下: Ndk使用17 FFmpeg使用4.0.2. clang编译使用的环境如下: Ndk使用21.4 FFmpeg使用6.1 FFmpeg下载地址:https://ffmpeg.org/…...

【AIGC-图片生成视频系列-2】八仙过海,各显神通:AI生成视频相关汇总剖析

最近「图片生成视频系列」层出不穷&#xff0c;我拜读并结合实践&#xff08;对&#xff0c;就是手撕代码&#xff0c;有开源就撕&#xff09;&#xff0c;并对以下几篇文章的相似点以及关键点稍微做个总结&#xff1a; 一. 生成视频中图像的一致性 在图像生成视频的这个过程…...

SpringBoot集成RabbitMq消息队列【附源码】

1. 项目背景 要啥项目背景&#xff0c;就是干&#xff01;&#xff01;&#xff01; SpringBoot版本&#xff1a;2.7.12 2. Rabbit MQ安装 这里讲解使用docker安装RabbitMQ&#xff0c;如果在windows下面安装RabbitMQ&#xff0c;参考下文 【笑小枫的按步照搬系列】Window…...

MySQL数据库的安装与环境配置

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

【广州华锐互动】VR科技科普展厅平台:快速、便捷地创建出属于自己的虚拟展馆

随着科技的不断进步&#xff0c;虚拟现实(VR)技术已经在许多领域取得了显著的成果。尤其是在展馆设计领域&#xff0c;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&#xff0c;全称是统一资源标识符&#xff08;Uniform Resource Ident…...

手拉手Springboot获取yml配置文件信息

环境介绍 技术栈 springboot3 软件 版本 mysql 8 IDEA IntelliJ IDEA 2022.2.1 JDK 17 Spring Boot 3.1.7 配置文件说明&#xff1a;启动配置文件优先级&#xff1a;properties高于yml 配置文件application.yml yml是 JSON 的超集&#xff0c;简洁而强大&#xf…...

行人重识别(ReID)基础知识入门

这里写目录标题 1、ReID技术概述1.1 基本原理1.2 实现流程1.3 重识别存在的技术挑战 2、训练数据格式介绍 1、ReID技术概述 1.1 基本原理 ReID&#xff0c;全称Re-identification&#xff0c;目的是利用各种智能算法在图像数据库中找到与要搜索的目标相似的对象。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请求时&#xff0c;Axios和Python中的requests库都是常用的工具。下面是它们的详细说明&#xff1a; Axios&#xff1a; Axios是一个基于Promise的HTTP客户端&#xff0c;主要用于浏览器和Node.js环境中发送HTTP请求。以下是Axios的一些特点和用法&#xff1…...

达梦数据库文档

1&#xff1a;达梦数据库(DM8)简介 达梦数据库管理系统是武汉达梦公司推出的具有完全自主知识产权的高性能数据库管理系统&#xff0c;简称DM。达梦数据库管理系统目前最新的版本是8.0版本&#xff0c;简称DM8。 DM8是达梦公司在总结DM系列产品研发与应用经验的基础上&#xf…...

CorelDRAW2024新功能有哪些?CorelDRAW2024最新版本更新怎么样?

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

基于Mapify的在线艺术地图设计

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

mxxWechatBot微信机器人V2版本文档说明

大家伙&#xff0c;我是雄雄&#xff0c;欢迎关注微信公众号&#xff1a;雄雄的小课堂。 先看这里 一、前言二、mxxWechatBot流程图三、怎么使用&#xff1f; 一、前言 经过不断地探索与研究&#xff0c;mxxWechatBot正式上线&#xff0c;届时全面开放使用。 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) 场景&#xff1a; 在同一个线程组里, 有10个并发, 7个做A业务, 3个做B业务,要模拟这种场景,可以通过吞吐量模拟器来实现。 添加吞吐量控制器 用法1: Percent Executions 在一个线程组内分别建立两个吞吐量控制器, 分别放业务A和业务B …...

【XML】TinyXML 详解(二):接口详解

【C】郭老二博文之&#xff1a;C目录 1、XML测试文件&#xff08;laoer.xml&#xff09; <?xml version"1.0" standalone"no" ?> <!-- Hello World !--> <root><child name"childName" id"1"><c_child…...

【机器学习】人工智能概述

人工智能&#xff08;Artificial Intelligence&#xff0c;简称AI&#xff09;是一门研究如何使机器能够像人一样思考、学习和执行任务的学科。它是计算机科学的一个重要分支&#xff0c;涉及机器学习、自然语言处理、计算机视觉等多个领域。 人工智能的概念最早可以追溯到20世…...

MPNet:旋转机械轻量化故障诊断模型详解python代码复现

目录 一、问题背景与挑战 二、MPNet核心架构 2.1 多分支特征融合模块(MBFM) 2.2 残差注意力金字塔模块(RAPM) 2.2.1 空间金字塔注意力(SPA) 2.2.2 金字塔残差块(PRBlock) 2.3 分类器设计 三、关键技术突破 3.1 多尺度特征融合 3.2 轻量化设计策略 3.3 抗噪声…...

超短脉冲激光自聚焦效应

前言与目录 强激光引起自聚焦效应机理 超短脉冲激光在脆性材料内部加工时引起的自聚焦效应&#xff0c;这是一种非线性光学现象&#xff0c;主要涉及光学克尔效应和材料的非线性光学特性。 自聚焦效应可以产生局部的强光场&#xff0c;对材料产生非线性响应&#xff0c;可能…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

【Go】3、Go语言进阶与依赖管理

前言 本系列文章参考自稀土掘金上的 【字节内部课】公开课&#xff0c;做自我学习总结整理。 Go语言并发编程 Go语言原生支持并发编程&#xff0c;它的核心机制是 Goroutine 协程、Channel 通道&#xff0c;并基于CSP&#xff08;Communicating Sequential Processes&#xff0…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Fabric V2.5 通用溯源系统——增加图片上传与下载功能

fabric-trace项目在发布一年后,部署量已突破1000次,为支持更多场景,现新增支持图片信息上链,本文对图片上传、下载功能代码进行梳理,包含智能合约、后端、前端部分。 一、智能合约修改 为了增加图片信息上链溯源,需要对底层数据结构进行修改,在此对智能合约中的农产品数…...

GO协程(Goroutine)问题总结

在使用Go语言来编写代码时&#xff0c;遇到的一些问题总结一下 [参考文档]&#xff1a;https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现&#xff1a; 今天在看到这个教程的时候&#xff0c;在自己的电…...

[大语言模型]在个人电脑上部署ollama 并进行管理,最后配置AI程序开发助手.

ollama官网: 下载 https://ollama.com/ 安装 查看可以使用的模型 https://ollama.com/search 例如 https://ollama.com/library/deepseek-r1/tags # deepseek-r1:7bollama pull deepseek-r1:7b改token数量为409622 16384 ollama命令说明 ollama serve #&#xff1a…...