C++ 单例对象自动释放(保姆级讲解)
目录
单例对象自动释放(重点*)
方式一:利用另一个对象的生命周期管理资源
方式二:嵌套类 + 静态对象(重点)
方式三:atexit + destroy
方式四:atexit + pthread_once
单例对象自动释放(重点*)
在类与对象的章节,我们学习了单例模式。单例对象由静态指针_pInstance保存,最终通过手动调用destroy函数进行释放。
现实工作中,单例对象是需要进行自动释放。程序在执行的过程中 ,需要判断有哪些地方发生了内存泄漏 ,此时需要工具valgrind的使用来确定。假设单例对象没有进行自动释放 ,那么valgrind工具会认为单例对象是内存泄漏。程序员接下来还得再次去确认到底是不是内存泄漏 ,增加了程序员的额外的工作。
那么如何实现单例对象的自动释放呢?
—— 看到自动就应该想到当对象被销毁时,析构函数会被自动调用。
方式一:利用另一个对象的生命周期管理资源
利用对象的生命周期管理资源——析构函数(在析构函数中会执行delete _p),当对象被销毁时会自动调用。
要注意:
(1)如果还手动调用了Singleton类的destroy函数,会导致double free问题,所以可以删掉destroy函数,将回收堆上的单例对象的工作完全交给AutoRelease对象
如果手动调用destory会将_p指向的空间释放掉,而__p还不是空指针,还会指向那一块空间,当程序结束,系统自动调用autorelease 的析构函数,就会出现double free的情况
(2)不能用多个AutoRelease对象托管同一个堆上的单例对象。这样也会出现double free的情况
对个对象管理一块空间,原理也是差不多。
class AutoRelease{
public:AutoRelease(Singleton * p): _p(p){ cout << "AutoRelease(Singleton*)" << endl; }~AutoRelease(){cout << "~AutoRelease()" << endl;if(_p){delete _p;_p = nullptr;}}
private:Singleton * _p;
};void test0(){AutoRelease ar(Singleton::getInstance());Singleton::getInstance()->print();
}
方式二:嵌套类 + 静态对象(重点)
AutoRelease类对象_ar是Singleton类的对象成员,创建Singleton对象,就会自动创建一个AutoRelease对象(静态区),它的成员函数可以直接访问 _pInstance
class Singleton
{class AutoRelease{public:AutoRelease(){}~AutoRelease(){if(_pInstance){delete _pInstance;_pInstance = nullptr;}}};//...
private://...int _ix;int _iy;static Singleton * _pInstance;static AutoRelease _ar;
};
Singleton* Singleton::_pInstance = nullptr;
//使用AutoReleas类的无参构造对_ar进行初始化
Singleton::AutoRelease Singleton::_ar;void test1(){Singleton::getInstance()->print();Singleton::getInstance()->init(10,80);Singleton::getInstance()->print();
}
程序结束时会自动销毁全局静态区上的_ar,调用AutoRelease的析构函数,在这个析构函数执行delete _pInstance的语句,这样又会调用Singleton的析构函数,再调用operator delete,回收掉堆上的单例对象。
我们利用嵌套类实现了一个比较完美的方案,不用担心手动调用了destroy函数。如果手动调用也不会出现double free的问题,因为有if判断。
方式三:atexit + destroy
很多时候我们需要在程序退出的时候做一些诸如释放资源的操作,但程序退出的方式有很多种,比如main()函数运行结束、在程序的某个地方用exit()结束程序、用户通过Ctrl+C操作来终止程序等等,因此需要有一种与程序退出方式无关的方法来进行程序退出时的必要处理。
方法就是用atexit函数来注册程序正常终止时要被调用的函数(C/C++通用)。
如果注册了多个函数,先注册的后执行。
class Singleton
{
public:static Singleton * getInstance(){if(_pInstance == nullptr){atexit(destroy); _pInstance = new Singleton(1,2);}return _pInstance;}//...
};
atexit注册了destroy函数,相当于有了一次必然会进行的destroy(程序结束时),即使手动调用了destroy,因为安全回收的机制,也不会有问题。
但是还遗留了一个问题,就是以上几种方式都无法解决多线程安全问题。以方式三为例,当多个线程同时进入if语句时,会造成单例对象被创建出多个,但是最终只有一个地址值会由_pInstance指针保存,因此造成内存泄漏。
可以使用饿汉式解决,但同时也可能带来内存压力(即使不用单例对象,也会被创建)
//对于_pInstance的初始化有两种方式//饱汉式(懒汉式)—— 懒加载,不使用到该对象,就不会创建 Singleton* Singleton::_pInstance = nullptr; //饿汉式 —— 最开始就创建(即使不使用这个单例对象) Singleton* Singleton::_pInstance = getInstance();
饿汉式可以确保getInstance函数的第一次调用一定是在_pInstance的初始化时,之后再调用getInstance函数的时候,都不会进入if分支创建出对象。
同时,还有一个要考虑的问题——如果多线程环境下手动调用了destroy函数,那么又会让_pInstance变为空指针,之后再调用getInstance函数还是有可能造成内存泄露,
故而应该将destroy函数私有。
下面为测试代码,可以自行测试
#include <iostream>
using std::cout;
using std::endl;class Singleton {
public://静态成员函数只允许访问静态成员因为,静态成员函数没有this指针找不到非静态成员static Singleton* getInstance(){//当多个线程进去if语句//会造成Singleton对象被创建多个//最终只有一个对象的地址被_pInstance保存//其他对象就形成内存泄漏if (_pInstance == nullptr){//第三种方法//先进行注册,在程序结束会自动调用destoryatexit(destory);_pInstance = new Singleton(1, 2);}return _pInstance;}void init(int x, int y){_ix = x;_iy = y;}void print() const {cout << "(" << _ix<< "," << _iy<< ")" << endl;}friend class AutoRelease;
private://如果是多线程环境,手动调用destory会使_pInstance 成为空指针,再次getInstance还是会造成内存泄漏,所以将destory//设置为私有,destory不能随意调用// //如果是单线程就不会有这种问题static void destory(){if (_pInstance){delete _pInstance;_pInstance = nullptr;cout << ">> delete heap" << endl;}}//单例模式将拷贝构造和赋值运算符重载函数删除掉Singleton(const Singleton& rhs) = delete;Singleton & operator= (const Singleton& rhs) = delete;//将构造函数设置为私有Singleton(int x, int y):_ix(x), _iy(y){cout << "Singleton(int , int)" << endl;}//将析构函数设置为私有~Singleton(){cout << "~Singleton()" << endl;}int _ix;int _iy;static Singleton* _pInstance;
};
//饱汉式(懒汉式)——懒加载
Singleton* Singleton::_pInstance = nullptr;//饿汉式
//开始就将单例对象创建出来,即使程序中不使用这个单例对象
Singleton* Singleton::_pInstance = Singleton::getInstance();class AutoRelease {
public:AutoRelease(Singleton* p): _p(p){cout << "AutoRelease(Singleton*)" << endl;}~AutoRelease() {cout << "~AutoRelease()" << endl;if (_p) {//这里会报错是因为执行delete表达式会先调用析构函数回收对象申请的空间,然后再调用operator delete库函数回收本对象的空间//要想访问私有成员,必须声明为友元delete _p;_p = nullptr;}}
private:Singleton* _p;
};void test0() {AutoRelease ar(Singleton::getInstance());Singleton::getInstance()->print();//下面两种情况都会double free//Singleton::destory();//AutoRelease ar2(Singleton::getInstance());
}
int main()
{test0();return 0;
}
方式四:atexit + pthread_once
Linux平台可以使用的方法(能够保证创建单例对象时的多线程安全)
pthread_once函数可以确保初始化代码只会执行一次。
传给pthread_once函数的第一个参数比较特殊,形式固定;第二个参数需要是一个静态函数指针,pthread_once可以确保这个函数只会执行一次。
class Singleton
{
public:static Singleton * getInstance(){pthread_once(&_once,init_r);return _pInstance;}void init(int x,int y){_ix = x;_iy = y;}void print(){cout << "(" << this->_ix<< "," << this->_iy<< ")" << endl;}
private:static void init_r(){_pInstance = new Singleton(1,2);atexit(destroy);}static void destroy(){if(_pInstance){delete _pInstance;_pInstance = nullptr;}}Singleton() = default;//C++11Singleton(int x,int y): _ix(x), _iy(y){cout << "Singleton(int,int)" << endl;}~Singleton(){cout << "~Singleton()" << endl;}Singleton(const Singleton & rhs) = delete;Singleton & operator=(const Singleton & rhs) = delete;
private:int _ix;int _iy;static Singleton * _pInstance;static pthread_once_t _once;
};
Singleton * Singleton::_pInstance = nullptr;
pthread_once_t Singleton::_once = PTHREAD_ONCE_INIT;
注意:
(1)如果手动调用init_r创建对象,没有通过getInstance创建对象,实际上绕开了pthread_once的控制,必然造成内存泄露 —— 需要将init_r私有
(2)如果手动调用了destroy函数,之后再使用getInstance来尝试创建对象,因为pthread_once的控制效果,不会再执行init_r函数,所以无法再创建出单例对象。所以不能允许手动调用destroy函数。
同时因为会使用atexit注册destroy函数实现资源回收,所以也不能将destroy删掉,应该将destroy私有,避免在类外手动调用。
![]()
下面为测试代码,可自行测试
#include <pthread.h>
#include <iostream>
using std::cout;
using std::endl;class Singleton {
public://静态成员函数只允许访问静态成员因为,静态成员函数没有this指针找不到非静态成员static Singleton* getInstance(){//当多个线程进去if语句//会造成Singleton对象被创建多个//最终只有一个对象的地址被_pInstance保存//其他对象就形成内存泄漏// if (_pInstance == nullptr)// {// //第三种方法// //先进行注册,在程序结束会自动调用destory// atexit(destory);// _pInstance = new Singleton(1, 2);// }//第一个参数传特定的参数,第二个参数传函数指针pthread_once( &once_control, init_r);return _pInstance;}void init(int x, int y){_ix = x;_iy = y;}void print() const {cout << "(" << _ix<< "," << _iy<< ")" << endl;}friend class AutoRelease;
private://如果将init_r设置为公有,我就可以使用域名多次调用它,每调用一次就会指向一个新的对象,前面的对象还没有销毁,缩回就会产生内存泄漏// 要将init_r设置为私有,这样只有类内可以调用,在类外不可以随意调用 static void init_r(){_pInstance = new Singleton(1, 2);//注册destory,程序结束自定调用destoryatexit(destory);}//如果将destory定义为公有,那么我可以调用,销毁单例对象,如果我想再次使用单例对象,就不能使用了,因为pthread_once会限制只能//创建一个单例对象,所以将destory设置为私有static void destory(){if (_pInstance){delete _pInstance;_pInstance = nullptr;cout << ">> delete heap" << endl;}}//单例模式将拷贝构造和赋值运算符重载函数删除掉Singleton(const Singleton& rhs) = delete;Singleton& operator= (const Singleton& rhs) = delete;//将构造函数设置为私有Singleton(int x, int y):_ix(x), _iy(y){cout << "Singleton(int , int)" << endl;}//将析构函数设置为私有~Singleton(){cout << "~Singleton()" << endl;}int _ix;int _iy;static Singleton* _pInstance;//因为上面为静态成员函数,所以这个参数也要初始化为静态参数static pthread_once_t once_control;
};
pthread_once_t Singleton::once_control = PTHREAD_ONCE_INIT;
//饱汉式(懒汉式)——懒加载
Singleton* Singleton::_pInstance = nullptr;//饿汉式
//开始就将单例对象创建出来,即使程序中不使用这个单例对象
Singleton* Singleton::_pInstance = Singleton::getInstance();class AutoRelease {
public:AutoRelease(Singleton* p): _p(p){cout << "AutoRelease(Singleton*)" << endl;}~AutoRelease() {cout << "~AutoRelease()" << endl;if (_p) {//这里会报错是因为执行delete表达式会先调用析构函数回收对象申请的空间,然后再调用operator delete库函数回收本对象的空间//要想访问私有成员,必须声明为友元delete _p;_p = nullptr;}}
private:Singleton* _p;
};void test0() {Singleton::getInstance()->init(1, 2);Singleton::getInstance()->print();// Singleton::destory();//下面两种情况都会double free//Singleton::destory();//AutoRelease ar2(Singleton::getInstance());
}
int main()
{test0();return 0;
}
相关文章:
C++ 单例对象自动释放(保姆级讲解)
目录 单例对象自动释放(重点*) 方式一:利用另一个对象的生命周期管理资源 方式二:嵌套类 静态对象(重点) 方式三:atexit destroy 方式四:atexit pthread_once 单例对象自动释…...
李录谈卖出股票的时机:价值投资的动态决策框架
作为最贴近芒格与巴菲特投资理念的中国投资人,李录对卖出时机的思考融合了价值投资的核心逻辑与实战经验。通过其在哥伦比亚大学的多场演讲及访谈(主要集中于2006年、2013年及后续公开内容),我们可以将其观点归纳为以下五个维度&a…...
Docker的简单使用(不全)
Docker Hello World Docker 允许在容器内运行应用程序,使用docker run命令来在容器内运行一个应用程序 输出Hello World runoobrunoob:~$ docker run ubuntu:15.10 /bin/echo "Hello world"Hello world docker:Docker的二进制执行文件 run…...
A2A与MCP:理解它们的区别以及何时使用
随着AI不断深入到商业工作流中,多个AI代理(Agent)之间的无缝协作成为了一个主要挑战。 为了解决这个问题,Google Cloud推出了一种名为Agent2Agent(A2A)的开放协议,旨在使不同平台和系统中的AI代…...
AI Agent开源技术栈
构建和编排Agent的框架 如果您是从头开始构建,请从这里开始。这些工具可以帮助您构建Agent的逻辑——做什么、何时做以及如何处理工具。您可以将其视为将原始语言模型转化为更自主的模型的核心大脑。 2. 计算机和浏览器的使用 一旦你的Agent能够规划,…...
判断用户选择的Excel单元格区域是否跨页?
VBA应用程序开发过程中,经常需要处理用户选中的单元格区域,有的应用场景中,需要限制用户选中区域位于同一页中(以打印预览显示的分页划分),但是VBA对象模型中并没有提供相应的接口,用于快速查询…...
驱动开发硬核特训 · Day 24(上篇):走进Linux内核时钟子系统 —— 硬件基础全解析
一、前言 在 SoC(System on Chip)设计中,“时钟(Clock)”不仅是信号同步的基石,也是各个模块协调运作的前提。没有合理的时钟体系,CPU无法运行,外设无法通信,存储器无法…...
【GPU 微架构技术】Pending Request Table(PRT)技术详解
PRT(Pending Request Table)是 GPU 中用于管理 未完成内存请求(outstanding memory requests)的一种硬件结构,旨在高效处理大规模并行线程的内存访问需求。与传统的 MSHR(Miss Status Handling Registers&a…...
角度(degrees)和弧度(radians)转换关系
目录 1.从角度转换到弧度: 2.从弧度转换到角度: 示例 将90度转换为弧度: 将π/3弧度转换为角度: 角度(degrees)和弧度(radians)之间的转换关系可以通过以下公式来实现ÿ…...
【大语言模型DeepSeek+ChatGPT+GIS+Python】AI大语言模型驱动的地质灾害全流程智能防治:风险评估、易发性分析与灾后重建多技术融合应用
地质灾害是指全球地壳自然地质演化过程中,由于地球内动力、外动力或者人为地质动力作用下导致的自然地质和人类的自然灾害突发事件。在降水、地震等自然诱因的作用下,地质灾害在全球范围内频繁发生。我国不仅常见滑坡灾害,还包括崩塌、泥石流…...
第十六届蓝桥杯 2025 C/C++组 25之和
目录 题目: 题目描述: 题目链接: 思路: 思路详解: 代码: 代码详解: 题目: 题目描述: 题目链接: P12339 [蓝桥杯 2025 省 B/Python B 第二场] 25 之和…...
万界星空科技QMS质量管理系统几大核心功能详解
QMS质量管理系统(Quality Management System)是一款专为现代企业设计的、全面且高效的质量管理工具,融合了现代质量管理理念与前沿的信息技术,旨在帮助企业构建完善的质量管理体系,确保产品和服务质量。以下为你详细介…...
SSR同构渲染深度解析
同构渲染(Isomorphic Rendering)是SSR(服务器端渲染)的核心概念,指同一套代码既能在服务器端运行,也能在客户端运行。下面我将从原理到实践全面介绍SSR同构渲染。 一、同构渲染核心原理 1. 基本工作流程 …...
【论文阅读/复现】RT-DETR的网络结构/训练/推理/验证/导出模型
利用ultralytics仓库,复现RT-DETR官方实验环境。 使用基于ResNet50和ResNet101的RT-DETR。 目录 一 RT-DETR的网络结构 1 编码器结构 2 RT-DETR 3 CCFF中的融合块 4 实验结果 二 RT-DETR的安装/训练/推理/验证/导出模型 1 安装 2 配置文件 3 训练 4 推理 …...
KUKA机器人关机时冷启动介绍
KUKA机器人在正常关机时,可以从示教器上操作。在示教器上操作时需要选择“冷启动”方式关闭计算机。等示教器屏幕关闭之后,再把主开关旋钮关闭。 一、先登录【管理员】权限,再在【主菜单】下选择【关机】。 二、在关机的默认中,…...
MCP Java SDK 介绍与使用指南
MCP与MCP Java SDK 概念 MCP 是什么? 模型上下文协议(Model Context Protocol, MCP)是用于标准化AI模型与工具间通信的规范。通过定义通用接口,确保不同AI组件(如模型推理服务、工具插件)能无缝协作。MCP …...
【Java核心】一文理解Java面向对象(超级详细!)
一:概述 1.1Java类及类的成员 属性、方法、构造器、代码块、内部类 1.2 面向对象的特征 封装、继承、多态(抽象) 1.3 其它关键字的使用 This、super、package、import、static、final、interface、abstract 1.4 面向对象和面向过程 &…...
2025年DDoS攻击防御全解析:应对超大流量的实战策略
一、2025年DDoS攻击的新趋势 超大规模攻击常态化:攻击流量突破300Gbps,部分案例甚至达到T级规模,传统单点防御已无法应对。 混合攻击模式盛行:攻击者结合应用层(HTTP Flood、CC攻击)与网络层(U…...
【动态导通电阻】 GaN PiN二极管电导调制对动态 RON 的影响
2020 年,浙江大学电气工程学院的Shaowen Han等人采用实验研究的方法,对垂直 GaN-on-GaN PiN 二极管中电导调制的瞬态行为及其对动态导通电阻(RON)的影响进行了深入探究。他们基于高质量的 GaN 基板开发的垂直 GaN-on-GaN 功率器件具有高电流容量和高击穿电压等优势,而与间…...
第十六届蓝桥杯 2025 C/C++B组第一轮省赛 全部题解(未完结)
目录 前言: 试题A:移动距离 试题C:可分解的正整数 试题D:产值调整 试题E:画展布置 前言: 我参加的是第一轮省赛,说实话第一次参加还是比较紧张的,真到考场上看啥都想打暴力&…...
MySQL 实战 45 讲 笔记 ----来源《极客时间》
01 | 基础架构:一条SQL查询语句是如何执行的? 1. MySQL 可以分为 Server层 和 存储引擎层 两部分。Server 层包括连接器、查询缓存、分析器、优化器、执行器等。存储引擎层支持 InnoDB、MyISAM等. (1) 连接器:管理连接,权限认证…...
海思SD3403边缘计算AI核心设备概述
1、海思SD3403边缘计算AI设备4TOPS算力(SD3403模组) 2、AI训练服务器 (≥60TOPS算力 INT8 算力越高AI训练速度越快) 3、普通监控IPC摄像机(低成本,批量化安装项目) 4、AI数据标定工作终端 (≥10TOPS算力 IN…...
算法设计:回溯法的基础原理与应用
目录 一、基本概念 二、适用问题 三、基本步骤 四、算法模式 递归回溯算法模式(求一个解) 非递归回溯算法模式(求一个解) 非递归回溯算法模式(求所有解) 五、经典应用 1数字组合问题 2数字排列问题…...
PyTorch 深度学习实战(23):多任务强化学习(Multi-Task RL)之扩展
之前的PyTorch 深度学习实战(23):多任务强化学习(Multi-Task RL)总结扩展运用代码如下: import torch import torch.nn as nn import torch.optim as optim import numpy as np from torch.distributions import Norm…...
音视频开发---视频编码基础
一、视频编码的必要性 1. 存储与传输成本高 未经编码压缩的原始视频的数据量极大,例如:一般电影的亮度信号采样频率为13.5MHz;色度信号的频带通常为亮度信号的一半或更少,为6.75MHz或3.375MHz。以4:2:2的采样频率为例,Y信号采用13.5MHz,色度信号U和V采用6.75MHz采样,…...
深入蜂窝物联网 第四章 Cat-1 与 5G RedCap:带宽、低时延与未来趋势
1. 前言与应用场景 随着物联网对带宽与时延的需求不断增长,LTE Cat-1 和 5G RedCap(Reduced Capability)应运而生: Cat-1:在传统 LTE 网络上提供最高 10 Mbps 下行、5 Mbps 上行,兼容性佳; 5G RedCap:在 5G NSA/SA 网络中提供 1–20 Mbps,时延可降至 10 ms 级,且模组…...
FPGA 39 ,FPGA 网络通信协议栈进阶,RGMII、ARP 与 UDP 协议与模块设计( RGMII、ARP、UDP原理与模块设计 )
目录 目录 一、核心原理 1.1 RGMII 接口:高效数据传输的物理桥梁 1.2 ARP 协议:IP 与 MAC 地址的动态映射引擎 1.3 UDP 协议:轻量级数据传输的高效选择 1.4 FPGA 实现流程 二、时序约束 2.1 时序约束理论…...
《系统分析师-第三阶段—总结(七)》
背景 采用三遍读书法进行阅读,此阶段是第三遍。 过程 本篇总结第13章第14章的内容 第13章 第14章 总结 系统设计分为概要设计与详细设计,然后重点讲解了处理流程设计,输入输出原型设计,面向对象设计、人机交互设计࿱…...
Lightroom 2025手机版:专业编辑,轻松上手
在摄影和图像编辑的世界里,Adobe Lightroom一直是一个不可或缺的工具。无论是专业摄影师还是摄影爱好者,都依赖它来提升照片的质量和视觉效果。今天,我们要介绍的 Lightroom 2025手机版,是Adobe公司为移动设备量身定制的照片编辑器…...
Cursor:AI时代的智能编辑器
在开发者社区掀起热潮的Cursor,正以破竹之势重塑编程工具格局。这款基于VS Code的AI优先编辑器,不仅延续了经典IDE的稳定基因,更通过深度集成的智能能力,将开发效率推向全新维度。2023年Anysphere公司获得的6000万美元A轮融资&…...
x86架构-k8s设置openebs的hostpath作为默认存储类的部署记录
文章目录 前言一、openebs是什么?二、准备步骤1.下载yaml文件2.准备一个新的单点k8s用于测试2.将openebs-operator.yaml中的镜像修改成使用国内加速源的 三、执行yaml1.openebs-operator.yaml2.local-hostpath-pvc.yaml和local-hostpath-pod.yaml 四、关于默认存储路…...
废品回收小程序:全链路数字化解决方案,赋能绿色未来
用户端:一键触达,便捷回收新体验 废品百科与估价指南:分类标准与实时价格一目了然,用户轻松掌握废品价值。一键预约,轻松回收:指尖轻点即可完成预约,上门服务省时省力。精准定位,导…...
Kotlin和JavaScript的对比
Kotlin和JavaScript有一些相似之处,但也存在显著的差异,下面从多个方面为你详细分析: 相似点 1. 语法灵活性 变量声明:二者在变量声明上都较为灵活。在JavaScript里,借助var、let和const可以声明变量。其中…...
蓝桥杯 5. 拼数
拼数 原题目链接 题目描述 给定 n 个正整数 a1, a2, …, an,你可以将它们任意排序。 现要将这 n 个数字连接成一排,即令相邻数字收尾相接,组成一个数。 问,这个数最大可以是多少。 输入格式 第一行输入一个正整数 n&#x…...
(即插即用模块-特征处理部分) 四十四、(2024 TGRS) FEM 特征增强模块
文章目录 1、Feature Enhancement Module2、代码实现 paper:FFCA-YOLO for Small Object Detection in Remote Sensing Images Code:https://github.com/yemu1138178251/FFCA-YOLO 1、Feature Enhancement Module 遥感图像中,小目标的特征通…...
“情况说明“以后,Unity XR 开发者如何选择?
Unity自4月7日发布了一系列“情况说明”,点进来的朋友应该都是看过的,此处不再赘述。此后引发了开发者社区的广泛关注和讨论。作为细分领域的XR开发者,此时也会面临着工具和版本的抉择或迷茫。笔者同样面临这些问题,因为要确定未来…...
c#版yolo可视化标注和一键免环境训练系统0429更新介绍
yolo免环境一键训练工具c#版yolo标注工具 ## 更新日志 - 2025.4.1: 1、软件上线 - 2025.4.6 1、调整界面,修复用户在1920*1080不能全部显示问题 2、修复 刷新当前目录 无法加载新增图片问题 3、新增 下一张图片快捷键 Enter或者ctrl↓&…...
Leetcode 3533. Concatenated Divisibility
Leetcode 3533. Concatenated Divisibility 1. 解题思路2. 代码实现 题目链接:3533. Concatenated Divisibility 1. 解题思路 这一题的话事实上如果我们原始的数组有序排列一下,然后依次考察每个元素是否可以被选用,此时,我们得…...
CosyVoice、F5-TTS、GPT-SoVITS、Fish-Speech声音模型项目深度对比:选型指南
在数字人、虚拟助手、智能客服等应用快速发展的背景下,文本转语音(TTS)和语音克隆技术已成为AI领域的核心技术之一。本文将对目前主流的四个开源语音合成项目——CosyVoice、F5-TTS、GPT-SoVITS 和 Fish-Speech进行全方位对比分析,…...
什么是DNS缓存?怎么清理DNS缓存?
在网络世界中,当我们输入一个网址想要访问某个网站时,计算机并不能直接识别“www.example.com”这样的网址,而是需要将其转换为对应的IP地址才能进行通信。这个转换过程由域名系统(DomainNameSystem,简称DNS࿰…...
基于STM32、HAL库的ATECC508A安全验证及加密芯片驱动程序设计
一、简介: ATECC508A是Microchip公司生产的一款加密认证芯片,提供以下主要特性: 基于硬件的ECDSA (Elliptic Curve Digital Signature Algorithm) 加密 支持SHA-256哈希算法 内置真随机数生成器(TRNG) 16个密钥存储槽位,可配置多种用途 支持I2C接口,最高1MHz时钟频率 超低…...
初中九年级学生体测准考证照片采集软件使用说明
随着中考体育测试的临近,各校陆续开始组织学生进行准考证照片、中考报名照片的采集工作。为方便学校集中采集和学生自主完成照片拍摄,本文将详细介绍使用"校园证件照采集平台"进行手机拍照线上采集的操作方法,帮助学校轻松完成体测…...
提供一些其他常见的字符串处理算法的Java示例
以下为你提供几种常见字符串处理算法的 Java 示例: 1. 字符串反转 反转字符串即把字符串中的字符顺序颠倒。 public class RemoveSpaces {public static String removeSpaces(String str) {return str.replaceAll("\\s", "");}public static…...
软件设计师-软考知识复习(2)
PERT图详解 PERT(Program Evaluation and Review Technique,计划评审技术)是一种用于项目管理的图形化工具,主要用于分析任务的时间安排、识别关键路径和优化资源分配。它特别适用于复杂项目,其中任务之间存在依赖关系…...
Qwen3快速部署 Qwen3-0.6B、Qwen3-8B、Qwen3-14B,Think Deeper
文章目录 0 Qwen31 平台与环境安装1 模型下载2 模型测试 0 Qwen3 今天,通义千问Qwen团队正式开源推出 Qwen3,这是 Qwen 系列大型语言模型的最新成员。最新的Qwen3系列模型具备双模推理能力(深入思考/快速响应)、支持119种语言及方…...
【C到Java的深度跃迁:从指针到对象,从过程到生态】第四模块·Java特性专精 —— 第十七章 IO流:超越FILE*的维度战争
一、从C文件操作到Java流的进化 1.1 C文件操作的原始挑战 C语言通过FILE*和低级文件描述符进行I/O操作,存在诸多限制: 典型文件复制代码: #include <stdio.h> int copy_file(const char* src, const char* dst) { FILE* in fope…...
Leetcode刷题记录22——滑动窗口最大值
题源:https://leetcode.cn/problems/sliding-window-maximum/description/?envTypestudy-plan-v2&envIdtop-100-liked 题目描述: 思路一: 暴力遍历法,通过一个长度为k的滑动窗口遍历nums,将其中最大的数依次记…...
React 第三十四节 Router 开发中 useLocation Hook 的用法以及案例详解
一、useLocation基础用法 作用:获取当前路由的 location 对象 返回对象结构: {pathname: "/about", // 当前路径search: "?namejohn", // 查询参数(URL参数)hash: "#contact", …...
BT134-ASEMI机器人功率器件专用BT134
编辑:LL BT134-ASEMI机器人功率器件专用BT134 型号:BT134 品牌:ASEMI 封装:TO-126 批号:最新 引脚数量:3 封装尺寸:如图 特性:双向可控硅 工作结温:-40℃~150℃…...
十五种光电器件综合对比——《器件手册--光电器件》
十五、光电器件 名称 原理 特点 应用 发光二极管(LED) 基于半导体材料的电致发光效应,当电流通过时,电子与空穴复合,释放出光子。 高效、节能、寿命长、响应速度快、体积小。 广泛用于指示灯、照明、显示&#…...