C++简单缓冲区类设计
目录
1.引言
2.静态缓冲区
3.动态缓冲区
4.数据引用类
5.自动数据引用类
6.几种缓冲区的类关系图
7.注意事项
8.完整代码
1.引言
在C++中,设计静态和动态缓冲区类时,需要考虑的主要差异在于内存管理的方式。静态缓冲区类通常使用固定大小的内存区域(即栈分配或静态分配),而动态缓冲区类则根据需要动态地分配和释放内存(即堆分配)。下面将分别展示这几种缓冲区类的基本设计思路。
不管是静态缓冲区还是动态缓冲区,都有统一的访问接口,于是提取共用方法,组成基础类:
template <class T>
class CSimpleDataBufferBase : public CNoncopyable
{
public:typedef T DataType;typedef T* DataTypePointer;typedef T& DataTypeReference;typedef const T ConstDataType;typedef const T* ConstDataTypePointer;typedef const T& ConstDataTypeReference;public:CSimpleDataBufferBase() {}virtual ~CSimpleDataBufferBase() {}public:virtual DWORD GetSize() const = 0;virtual DataTypePointer GetData() = 0;virtual ConstDataTypePointer GetData() const = 0;virtual DWORD GetMaxSize() const = 0;operator DataTypePointer() { return GetData(); } DataTypeReference operator*() { return *GetData(); }DataTypeReference operator[](int nIndex);virtual BOOL SetData(ConstDataTypePointer pData, DWORD dwSize) = 0;virtual void Clear() = 0;
};
接口设计要点:
1)CSimpleDataBufferBase继承CNoncopyable,禁止构造拷贝和赋值拷贝。
2)访问缓冲区数据的接口,const和非const版本。
3)重载操作符*或[]访问缓冲区元素的数据
template <class T>
typename CSimpleDataBufferBase<T>::DataTypeReference CSimpleDataBufferBase<T>::operator[](int nIndex)
{if ( (nIndex >= 0) && (nIndex < (int)GetSize())){DataTypePointer pData = GetData();return pData[nIndex];}else{throw std::out_of_range("invalid data<nIndex> position");}
}
4)往缓冲区写数据接口,接收的是const T*和数据的长度。
5)获取缓冲区的上限。
5)清空缓冲区。
2.静态缓冲区
静态缓冲区类通常包含一个固定大小的数组(或其他容器,但数组是最直接的例子),并提供一系列方法来操作这个数组。 静态缓冲区类CStaticSimpleDataBufferT实现代码如下:
//数据静态分配
template <class T>
class CStaticSimpleDataBufferT : public CSimpleDataBufferBase<T>
{
public:CStaticSimpleDataBufferT(DWORD dwMaxSize = MAX_STATIC_SIMPLE_BUFFER_SIZE);virtual ~CStaticSimpleDataBufferT() { }public:DWORD GetSize() const { return m_dwDataLen; }DataTypePointer GetData() { return m_sData ;}ConstDataTypePointer GetData() const { return m_sData ;}BOOL SetData(ConstDataTypePointer pData, DWORD dwSize);DWORD GetMaxSize() const { return m_dwMaxDataSize; }void Clear() { m_dwDataLen = 0; }private:DataType m_sData[MAX_STATIC_SIMPLE_BUFFER_SIZE];DWORD m_dwDataLen;const DWORD m_dwMaxDataSize;
};
从实现的代码看,静态缓冲区就是在内存中事先分配好一段空间,这种分配一般是在栈中进行,分配速度特别快,但是不灵活,不能按照用户的大小需求分配空间。
3.动态缓冲区
动态缓冲区类通常基于动态内存分配(如new和delete)来满足用户的需求。静态缓冲区的大小在编译时确定,而动态缓冲区的大小则根据需要动态变化。静态缓冲区适用于那些大小已知且不会改变的场景,而动态缓冲区则更灵活,适用于大小可能变化的场景。动态缓冲区类CDynamicSimpleDataBufferT实现代码如下:
//CSimpleDataBufferBase的默认适配器
template <class T>
class CSimpleDataBufferAdapter : public CSimpleDataBufferBase<T>
{
public:CSimpleDataBufferAdapter() : m_pData(NULL),m_dwDataLen(0) { }virtual ~CSimpleDataBufferAdapter() { }public:DWORD GetSize() const { return m_dwDataLen; }BOOL SetData(ConstDataTypePointer pData, DWORD dwSize) { assert(0); return FALSE; }void SetSize(DWORD dwSize) { m_dwDataLen = dwSize; }DWORD GetMaxSize() const { assert(0); return 0; }void Clear() { assert(0); }DataTypePointer GetData() { return m_pData ;}ConstDataTypePointer GetData() const { return m_pData ;}protected:DataTypePointer m_pData;DWORD m_dwDataLen;
};/动态缓冲区
template <class T>
class CDynamicSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CDynamicSimpleDataBufferT(DWORD dwMaxSize = MAX_DYNAMIC_SIMPLE_BUFFER_SIZE);virtual ~CDynamicSimpleDataBufferT() { ClearData(); }public:void Clear() { m_dwDataLen = 0; }DWORD GetMaxSize() const { return m_dwMaxDataSize; }BOOL SetData(ConstDataTypePointer pData, DWORD dwSize);protected:void ClearData();private:const DWORD m_dwMaxDataSize;
};
构造函数、析构函数、赋值函数实现如下:
//构造函数
template <class T>
CDynamicSimpleDataBufferT<T>::CDynamicSimpleDataBufferT(DWORD dwMaxSize)
: m_dwMaxDataSize(dwMaxSize)
{m_pData = new T[dwMaxSize];if (m_pData == NULL)throw std:: bad_alloc("new T Array Failed");m_dwDataLen = 0;assert(m_pData != NULL);assert(m_dwDataLen >= 0);
}//清空数据函数
template <class T>
void CDynamicSimpleDataBufferT<T>::ClearData()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}//赋值函数
template <class T>
BOOL CDynamicSimpleDataBufferT<T>::SetData(ConstDataTypePointer pData, DWORD dwSize)
{int i;if (dwSize > m_dwMaxDataSize)return FALSE;for (i = 0; i < (int)dwSize; i++)m_pData[i] = pData[i];m_dwDataLen = dwSize;return TRUE;
}
析构函数自动调用了Clear函数,释放了内存,这样就不怕退出的时候出现内存泄漏。
4.数据引用类
在前面讲解的静态缓冲区和动态缓冲区内部都需要开辟空间,而数据引用类不需要开辟空间;CRefSimpleDataBufferT的具体实现如下:
template <class T>
class CRefSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CRefSimpleDataBufferT() { }CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);virtual ~CRefSimpleDataBufferT() { }public:BOOL SetData(ConstDataTypePointer pBuffer, DWORD dwSize);void Clear();
};template <class T>
CRefSimpleDataBufferT<T>::CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize)
{m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;
}template <class T>
void CRefSimpleDataBufferT<T>::Clear()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}template <class T>
BOOL CRefSimpleDataBufferT<T>::SetData(typename CRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
{Clear();m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;return TRUE;
}
从实现的代码来看,如果引用的数据是动态分配的,就可以调用Clear函数释放内存,反之,则不需要调用。
5.自动数据引用类
自动数据引用类就是引用外部的动态分配的数据源,并自动释放这个数据源的内存。CAutoRefSimpleDataBufferT的实现代码如下:
//自动释放动态分配的数据引用类
template <class T>
class CAutoRefSimpleDataBufferT : public CRefSimpleDataBufferT<T>
{
public:CAutoRefSimpleDataBufferT() { }CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer);void Clear();DataTypePointer operator->() { return GetData(); }ConstDataTypePointer operator->() const { return GetData(); }virtual ~CAutoRefSimpleDataBufferT();
};template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
: CRefSimpleDataBufferT<T>(pBuffer, dwSize)
{
}template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer)
: CRefSimpleDataBufferT<T>(pBuffer, 1)
{
}template <class T>
void CAutoRefSimpleDataBufferT<T>::Clear()
{if (1 == m_dwDataLen)delete m_pData;elseCRefSimpleDataBufferT<T>::Clear();
}template <class T>
CAutoRefSimpleDataBufferT<T>::~CAutoRefSimpleDataBufferT()
{Clear();
}
CAutoRefSimpleDataBufferT和CRefSimpleDataBufferT的不同点就在于析构函数自动调用了Clear函数,释放了数据源的内存。
6.几种缓冲区的类关系图

7.注意事项
1)静态成员变量的初始化:静态成员变量需要在类外进行初始化,并且只能初始化一次。
2)线程安全:如果多个线程可能同时访问这个静态缓冲区,你需要实现适当的同步机制来避免数据竞争和不一致。
3)资源管理:静态缓冲区在程序结束时自动销毁,但如果你在其中存储了动态分配的资源(如指针指向的堆内存),你需要确保在程序结束前正确释放这些资源。
4)性能考虑:静态缓冲区大小固定,如果缓冲区大小设置不当,可能会导致频繁的内存溢出或内存浪费。
5)并发访问:在并发环境中,如果多个线程可能同时写入或读取缓冲区,需要考虑使用互斥锁(如std::mutex)来同步访问。
8.完整代码
Noncopyable.h
/*************************************************************************// 功能: 防止拷贝类// 备注: *************************************************************************/
#pragma onceclass CNoncopyable
{
public:CNoncopyable() {}~CNoncopyable() {}protected:CNoncopyable(const CNoncopyable& src); //拷贝构造函数const CNoncopyable& operator=(const CNoncopyable& src); //赋值函数
};
SimpleDataBuffer.h
#pragma once
#include "Noncopyable.h"
#include <assert.h>
#include <new>
#include <stdexcept>
using namespace std;#define MAX_STATIC_SIMPLE_BUFFER_SIZE (4*1024) //4K
#define MAX_DYNAMIC_SIMPLE_BUFFER_SIZE (800*1024) //800Ktemplate <class T>
class CSimpleDataBufferBase : public CNoncopyable
{
public:typedef T DataType;typedef T* DataTypePointer;typedef T& DataTypeReference;typedef const T ConstDataType;typedef const T* ConstDataTypePointer;typedef const T& ConstDataTypeReference;public:CSimpleDataBufferBase() {}virtual ~CSimpleDataBufferBase() {}public:virtual DWORD GetSize() const = 0;virtual DataTypePointer GetData() = 0;virtual ConstDataTypePointer GetData() const = 0;virtual DWORD GetMaxSize() const = 0;operator DataTypePointer() { return GetData(); } DataTypeReference operator*() { return *GetData(); }DataTypeReference operator[](int nIndex);virtual BOOL SetData(ConstDataTypePointer pData, DWORD dwSize) = 0;virtual void SetSize(DWORD dwSize) = 0;virtual void Clear() = 0;
};template <class T>
typename CSimpleDataBufferBase<T>::DataTypeReference CSimpleDataBufferBase<T>::operator[](int nIndex)
{if ( (nIndex >= 0) && (nIndex < (int)GetSize())){DataTypePointer pData = GetData();return pData[nIndex];}else{throw std::out_of_range("invalid data<nIndex> position");}
}//数据静态分配
template <class T>
class CStaticSimpleDataBufferT : public CSimpleDataBufferBase<T>
{
public:CStaticSimpleDataBufferT(DWORD dwMaxSize = MAX_STATIC_SIMPLE_BUFFER_SIZE);virtual ~CStaticSimpleDataBufferT() { }public:DWORD GetSize() const { return m_dwDataLen; }DataTypePointer GetData() { return m_sData ;}ConstDataTypePointer GetData() const { return m_sData ;}BOOL SetData(ConstDataTypePointer pData, DWORD dwSize);void SetSize(DWORD dwSize) { m_dwDataLen = dwSize; }DWORD GetMaxSize() const { return m_dwMaxDataSize; }void Clear() { m_dwDataLen = 0; }private:DataType m_sData[MAX_STATIC_SIMPLE_BUFFER_SIZE];DWORD m_dwDataLen;const DWORD m_dwMaxDataSize;
};template <class T>
CStaticSimpleDataBufferT<T>::CStaticSimpleDataBufferT(DWORD dwMaxSize)
: m_dwDataLen(0),m_dwMaxDataSize(dwMaxSize)
{
}template <class T>
BOOL CStaticSimpleDataBufferT<T>::SetData(ConstDataTypePointer pData, DWORD dwSize)
{int i;if (dwSize > m_dwMaxDataSize)return FALSE;for (i = 0; i < (int)dwSize; i++)m_sData[i] = pData[i];m_dwDataLen = dwSize;return TRUE;
}
///
template <class T>
class CSimpleDataBufferAdapter : public CSimpleDataBufferBase<T>
{
public:CSimpleDataBufferAdapter() : m_pData(NULL),m_dwDataLen(0) { }virtual ~CSimpleDataBufferAdapter() { }public:DWORD GetSize() const { return m_dwDataLen; }BOOL SetData(ConstDataTypePointer pData, DWORD dwSize) { assert(0); return FALSE; }void SetSize(DWORD dwSize) { m_dwDataLen = dwSize; }DWORD GetMaxSize() const { assert(0); return 0; }void Clear() { assert(0); }DataTypePointer GetData() { return m_pData ;}ConstDataTypePointer GetData() const { return m_pData ;}protected:DataTypePointer m_pData;DWORD m_dwDataLen;
};/
template <class T>
class CDynamicSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CDynamicSimpleDataBufferT(DWORD dwMaxSize = MAX_DYNAMIC_SIMPLE_BUFFER_SIZE);virtual ~CDynamicSimpleDataBufferT() { ClearData(); }public:void Clear() { m_dwDataLen = 0; }DWORD GetMaxSize() const { return m_dwMaxDataSize; }BOOL SetData(ConstDataTypePointer pData, DWORD dwSize);protected:void ClearData();private:const DWORD m_dwMaxDataSize;
};template <class T>
CDynamicSimpleDataBufferT<T>::CDynamicSimpleDataBufferT(DWORD dwMaxSize)
: m_dwMaxDataSize(dwMaxSize)
{m_pData = new T[dwMaxSize];if (m_pData == NULL)throw std:: bad_alloc("new T Array Failed");m_dwDataLen = 0;assert(m_pData != NULL);assert(m_dwDataLen >= 0);
}template <class T>
void CDynamicSimpleDataBufferT<T>::ClearData()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}template <class T>
BOOL CDynamicSimpleDataBufferT<T>::SetData(ConstDataTypePointer pData, DWORD dwSize)
{int i;if (dwSize > m_dwMaxDataSize)return FALSE;for (i = 0; i < (int)dwSize; i++)m_pData[i] = pData[i];m_dwDataLen = dwSize;return TRUE;
}
//
template <class T>
class CRefSimpleDataBufferT : public CSimpleDataBufferAdapter<T>
{
public:CRefSimpleDataBufferT() { }CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);virtual ~CRefSimpleDataBufferT() { }public:BOOL SetData(ConstDataTypePointer pBuffer, DWORD dwSize);void Clear();
};template <class T>
CRefSimpleDataBufferT<T>::CRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize)
{m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;
}template <class T>
void CRefSimpleDataBufferT<T>::Clear()
{if (m_pData)delete []m_pData;m_pData = NULL;m_dwDataLen = 0;
}template <class T>
BOOL CRefSimpleDataBufferT<T>::SetData(typename CRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
{Clear();m_pData = const_cast<DataTypePointer>(pBuffer);m_dwDataLen = dwSize;return TRUE;
}//自动释放动态分配的数据引用类
template <class T>
class CAutoRefSimpleDataBufferT : public CRefSimpleDataBufferT<T>
{
public:CAutoRefSimpleDataBufferT() { }CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer, DWORD dwSize);CAutoRefSimpleDataBufferT(ConstDataTypePointer pBuffer);void Clear();DataTypePointer operator->() { return GetData(); }ConstDataTypePointer operator->() const { return GetData(); }virtual ~CAutoRefSimpleDataBufferT();
};template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer, DWORD dwSize)
: CRefSimpleDataBufferT<T>(pBuffer, dwSize)
{
}template <class T>
CAutoRefSimpleDataBufferT<T>::CAutoRefSimpleDataBufferT(typename CAutoRefSimpleDataBufferT<T>::ConstDataTypePointer pBuffer)
: CRefSimpleDataBufferT<T>(pBuffer, 1)
{
}template <class T>
void CAutoRefSimpleDataBufferT<T>::Clear()
{if (1 == m_dwDataLen)delete m_pData;elseCRefSimpleDataBufferT<T>::Clear();
}template <class T>
CAutoRefSimpleDataBufferT<T>::~CAutoRefSimpleDataBufferT()
{Clear();
}相关文章:
C++简单缓冲区类设计
目录 1.引言 2.静态缓冲区 3.动态缓冲区 4.数据引用类 5.自动数据引用类 6.几种缓冲区的类关系图 7.注意事项 8.完整代码 1.引言 在C中,设计静态和动态缓冲区类时,需要考虑的主要差异在于内存管理的方式。静态缓冲区类通常使用固定大小的内存区域…...
MySQL 数据库
1. MySQL 数据库的基础知识 这一部分将带你了解 MySQL 数据库的核心概念。无论你是初学者还是想要巩固基础,这部分内容将帮助你打下扎实的基础。 数据库的定义与作用:什么是数据库?MySQL 与其他数据库系统的比较。MySQL 安装与配置…...
基于单片机的智能校园照明系统
由于校园用电量较大,本设计可以根据实际环境情况的改变,实现实时照明的控制。本设计以单片机芯片为控制芯片,热释电传感器采集教室中学生出入的信息,并把信息传递给单片机芯片,单片机芯片根据传感器传递过来的信息来控…...
高性能分布式搜索引擎Elasticsearch详解
♥️作者:小宋1021 🤵♂️个人主页:小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识,和大家一起努力呀!!! 🎈🎈加油! 加油!…...
连锁收银系统的五大功能 选择开源收银系统三要素
连锁收银系统的五大功能,很多新手是不清楚的,老手也只是知道一些大概,今天,商淘云为大家分享收银系统的五大功能,尤其是第五个,大部分人不清楚,有的企业前面选了不合适的收银系统,导…...
虚幻引擎解决构建问题
1.Intermediate 文件夹 在 Unreal Engine中,Intermediate 文件夹扮演着构建过程中的临时存储角色。具体来说,Intermediate 文件夹用于存放在编译和构建项目过程中生成的中间文件,这些文件包括但不限于: 编译中间文件:…...
C++基础知识:C++中读文件的四种简单方式
1.读取文件的步骤: 读文件步骤如下: 1.包含头文件 #include <fstream> 2.创建流对象 ifstream ifs; 3.打开文件并判断文件是否打开成功 ifs.open(“文件路径”,打开方式); 4. 读数据 四种方式读取 5.关闭文件 ifs.close(); 读取方法一: #include…...
【人工智能】多模态AI:如何通过融合文本、图像与音频重塑智能系统未来
1. 引言 在人工智能领域,多模态AI 是一项令人兴奋的新兴技术,旨在通过结合文本、图像和音频等多种数据模态,打造更加智能化和人性化的系统。随着深度学习和自然语言处理(NLP)的飞速发展,多模态AI正在为下一…...
通过重写QStyle控制QT控件样式
文章目录 创建自定义 QStyle 子类重写绘制方法调整大小和边距使用自定义样式在Qt应用程序中,QStyle类是负责所有控件(如按钮、滚动条、复选框等)的外观和行为的基类。重写QStyle允许你自定义控件的外观和感觉,实现独特的界面设计。下面介绍一下如何通过重写QStyle控制QT控件的…...
WPF入门教学十八 动画入门
WPF(Windows Presentation Foundation)是微软推出的一种用于创建Windows客户端应用程序的用户界面框架。WPF 提供了丰富的动画支持,可以通过XAML或者代码来实现各种动画效果。以下是一个简单的WPF动画入门教学,我们将使用XAML来创…...
电信光猫破解记录
设置桥接上网什么的都需要光猫超级管理员密码,记录一下自己破解电信光猫超级管理员密码的过程 1、MAC转初始密码串 记录MAC地址 MAC地址在光猫背后 生成密码串 把MAC地址中的横杠删除,得到一个密码串 2、windows开启 tel功能 打开控制面板 进入程序和…...
鸿蒙界面开发(九):列表布局 (List)
列表布局 当列表项达到一定数量,内容超过屏幕大小时,可以自动提供滚动功能。它适合用于呈现同类数据类型或数据类型集,例如图片和文本。在列表中显示数据集合是许多应用程序中的常见要求(如通讯录、音乐列表、购物清单等…...
微服务远程调用(nacos及OpenFeign简单使用)
问题:在微服务中,每个项目是隔离开的,当有一个项目请求其他项目中的数据时,必须发起网络请求,本文即对此问题展开讨论。 1.使用restTemplate发送请求 //发送请求ResponseEntity<List<ItemDTO>> response …...
Protobuf vs Thrift: 高性能序列化框架的对比与分析
Protobuf(Protocol Buffers)和Thrift都是高性能、跨语言的序列化框架,它们在数据通信和服务开发中扮演着重要角色。下面从多个方面对它们进行详细对比: 一、概述 1. Protobuf 简介:Protobuf是Google开发的一种语言中…...
LeetCode Hot100 C++ 哈希 1.两数之和
LeetCode Hot100 C 1.两数之和 给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个整数,并返回它们的数组下标。 你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。 你可以按…...
Windows下安装Neo4j流程
Neo4j简介 Neo4j 是一个基于图形结构的 NoSQL 数据库,专门用于存储和管理图数据。与传统的关系型数据库不同,Neo4j 使用 图(graph)的形式来表示数据,其中数据点(称为 节点)通过 边(…...
Spring IDEA 2024 自动生成get和set以及toString方法
1.简介 在IDEA中使用自带功能可以自动生成get和set以及toString方法 2.步骤 在目标类中右键,选择生成 选择Getter和Setter就可以生成每个属性对应的set和get方法, 选择toString就可以生成类的toString方法,...
部署my2sql
binlog解析及闪回工具 MySQL闪回工具简介 及 binlog2sql工具用法 安装: unzip my2sql-master.zip cd my2sql-master go build . 使用要求: 1、使用回滚/闪回功能时,binlog格式必须为row,且binlog_row_imagefull, DML统计以及大…...
Android Studio 真机USB调试运行频繁掉线问题
一、遇到问题 Android Studio使用手机运行项目时,总是频繁掉线,连接很不稳定,动不动就消失,基本上无法使用 二、问题出现原因 1、硬件问题:数据线 换条数据线试试,如果可以,那就是数据线的…...
如何通过费曼技巧理解复杂主题
在软件工程领域,知道某件事的名称和真正理解其工作原理之间存在巨大差异。 你可能知道某台机器或某个软件的名称,但你是否真的理解它是如何运作和完成任务的? 在如此复杂且不断发展的领域中,这种区别至关重要。 通过“教学反馈…...
大数据学习栈记——Neo4j的安装与使用
本文介绍图数据库Neofj的安装与使用,操作系统:Ubuntu24.04,Neofj版本:2025.04.0。 Apt安装 Neofj可以进行官网安装:Neo4j Deployment Center - Graph Database & Analytics 我这里安装是添加软件源的方法 最新版…...
Appium+python自动化(十六)- ADB命令
简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...
解决Ubuntu22.04 VMware失败的问题 ubuntu入门之二十八
现象1 打开VMware失败 Ubuntu升级之后打开VMware上报需要安装vmmon和vmnet,点击确认后如下提示 最终上报fail 解决方法 内核升级导致,需要在新内核下重新下载编译安装 查看版本 $ vmware -v VMware Workstation 17.5.1 build-23298084$ lsb_release…...
ServerTrust 并非唯一
NSURLAuthenticationMethodServerTrust 只是 authenticationMethod 的冰山一角 要理解 NSURLAuthenticationMethodServerTrust, 首先要明白它只是 authenticationMethod 的选项之一, 并非唯一 1 先厘清概念 点说明authenticationMethodURLAuthenticationChallenge.protectionS…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...
【Java_EE】Spring MVC
目录 Spring Web MVC 编辑注解 RestController RequestMapping RequestParam RequestParam RequestBody PathVariable RequestPart 参数传递 注意事项 编辑参数重命名 RequestParam 编辑编辑传递集合 RequestParam 传递JSON数据 编辑RequestBody …...
IoT/HCIP实验-3/LiteOS操作系统内核实验(任务、内存、信号量、CMSIS..)
文章目录 概述HelloWorld 工程C/C配置编译器主配置Makefile脚本烧录器主配置运行结果程序调用栈 任务管理实验实验结果osal 系统适配层osal_task_create 其他实验实验源码内存管理实验互斥锁实验信号量实验 CMISIS接口实验还是得JlINKCMSIS 简介LiteOS->CMSIS任务间消息交互…...
【Oracle】分区表
个人主页:Guiat 归属专栏:Oracle 文章目录 1. 分区表基础概述1.1 分区表的概念与优势1.2 分区类型概览1.3 分区表的工作原理 2. 范围分区 (RANGE Partitioning)2.1 基础范围分区2.1.1 按日期范围分区2.1.2 按数值范围分区 2.2 间隔分区 (INTERVAL Partit…...
Reasoning over Uncertain Text by Generative Large Language Models
https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...
android13 app的触摸问题定位分析流程
一、知识点 一般来说,触摸问题都是app层面出问题,我们可以在ViewRootImpl.java添加log的方式定位;如果是touchableRegion的计算问题,就会相对比较麻烦了,需要通过adb shell dumpsys input > input.log指令,且通过打印堆栈的方式,逐步定位问题,并找到修改方案。 问题…...
