粉色做网站背景图片/个人网站怎么做
目录
智能指针意义
智能指针的使用及原理
RAII
智能指针的原理
std::auto_ptr
std::auto_ptr的模拟实现
std::unique_ptr
std::unique_ptr模拟实现
循环引用问题
智能指针意义
#问:为什么需要智能指针?
#include <iostream>
#include <stdexcept>int div()
{int a, b;std::cin >> a >> b;if (b == 0)throw std::invalid_argument("除0错误");return a / b;
}void Func()
{// 1、如果p1这里new 可能会抛异常。// 2、如果p2这里new 可能会抛异常。// 3、如果div调用也可能会抛异常。int *p1 = new int;int *p2 = new int;std::cout << div() << std::endl;delete p1;delete p2;
}int main()
{try{Func();}catch (std::exception &e){std::cout << e.what() << std::endl;}return 0;
}
在一异常中,因为异常会导致程序的执行流乱跳,所以很多个会出现异常的代码,放在一起就很容易其中一个抛异常,而导致其余的未执行 / 需要释放的空间未释放。如上:p2出问题,需要释放p1,div出问题,需要释放p1、p2,智能指针就是用来解决这个问题。
智能指针的使用及原理
RAII
RAII(Resource Acquisition Is Initialization - 获取资源即初始化)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。资源:需要手动释放的。(RAII:请求到志愿就初始化)
初始化指的是:
调用一个其他类的构造函数,利用其他类的生命周期来进行管理。
在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上:把管理一份资源的责任托管给了一个对象。
就是在获取到资源的时候,交给一个对象管理,于是在该对象的生命周期里这个资源始终有效。而这个对象无论如何是异常还是正常结束,都会调用这个对象的析构函数,于是利用这个对象的析构函数释放资源。
这种做法有两大好处:
- 不需要显式地释放资源。
- 采用这种方式,对象所需的资源在其生命期内始终保持有效。
智能指针的原理
最基础的智能指针:
// 使用RAII思想设计的SmartPtr类
template <class T>
class SmartPtr
{
public:SmartPtr(T *ptr = nullptr) // 将资源给智能指针: _ptr(ptr) // 智能指针将资源保存{}~SmartPtr(){if (_ptr)delete _ptr;}private:T *_ptr;
};
#include <iostream>
#include <stdexcept>// 1、利用RAII思想设计delete资源的类
// 2、像指针一样的行为
template<class T>
class SmartPtr
{
public:SmartPtr(T* ptr) // 将资源给智能指针:_ptr(ptr) // 智能指针将资源保存{}~SmartPtr(){cout << "delete:" << _ptr << endl;delete _ptr;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;
};int div()
{int a, b;std::cin >> a >> b;if (b == 0)throw std::invalid_argument("除0错误");return a / b;
}
void Func()
{// sp1、sp2出作用域会调用析构函数,抛异常,栈帧会正常结束SmartPtr<int> sp1(new int);SmartPtr<int> sp2(new int);*sp1 = 0;*sp2 = 2;std::cout << div() << std::endl;
}int main()
{try{Func();}catch (std::exception& e){std::cout << e.what() << std::endl;}return 0;
}
- RAII特性。
- 重载operator*和opertaor->,具有像指针一样的行为。
Note:
智能指针看起来很完美,但是又一个致命的问题:智能指针的拷贝问题。默认的拷贝构造只会进行浅拷贝,就会导致一个地址被析构两次。主要原因就是:智能指针管理资源的释放。
解决方案:
问:深拷贝?
不能,违背了智能指针的功能需求,需要的就是浅拷贝,智能指针不知道该空间有多大,只是对与指针的保存。
(问题先保留看看C++库中的解决方式)
std::auto_ptr
http://www.cplusplus.com/reference/memory/auto_ptr/
#include <iostream>
#include <memory>class A
{
public:~A(){std::cout << "~A()" << std::endl;}int _a1 = 0;int _a2 = 0;
};int main()
{std::auto_ptr<A> ap1(new A);ap1->_a1++;ap1->_a2++;std::auto_ptr<A> ap2(ap1);//ap1->_a1++;//ap1->_a2++;return 0;
}

总结:
std::auto_ptr是采用的资源管理权转移。但是,是不负责任的拷贝,会导致被拷贝对象悬空。所以多年以来被挂在耻辱柱上,很多公司明确要求不能使用它。
std::auto_ptr的模拟实现
注意:不是交换 —— 是管理权的转移,所以如果是:
std::auto_ptr<A> ap1(new A);
std::auto_ptr<A> ap2(new A);
ap2 = ap1;
ap2是获取ap1的资源(资源管理权的转移) ,ap2之前的资源自动调用析构释放,ap1置空(nullptr)。
namespace cr
{template<class T>class auto_ptr {public:auto_ptr(T* ptr = nullptr): _ptr(ptr){}// 不是交换 —— 是管理权的转移// 不是交换auto_ptr(auto_ptr<T>& ap):_ptr(ap._ptr){ap._ptr = nullptr;}// 不是交换 —— 是管理权的转移// ap1 = ap2;auto_ptr<T>& operator=(auto_ptr<T>& ap){if (this != &ap){if (_ptr){cout << "Delete:" << _ptr << endl;delete _ptr;}_ptr = ap._ptr;ap._ptr = nullptr;}return *this;}~auto_ptr(){if (_ptr){cout << "Delete:" << _ptr << endl;delete _ptr;}}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};
}
std::unique_ptr
C++11中开始提供更靠谱的unique_ptr
https://cplusplus.com/reference/memory/unique_ptr/
std::unique_ptr模拟实现
namespace cr
{template<class T>class unique_ptr{private: // 防止有人跑到类外实现写一个浅拷贝// 防拷贝 C++98 - 当时还是boost库中// 只声明不实现 // unique_ptr(unique_ptr<T>& ap);// unique_ptr<T>& operator=(unique_ptr<T>& ap);public:unique_ptr(T* ptr = nullptr): _ptr(ptr){}// 防拷贝 C++11unique_ptr(unique_ptr<T>& ap) = delete;unique_ptr<T>& operator=(unique_ptr<T>& ap) = delete;~unique_ptr(){if (_ptr){cout << "Delete:" << _ptr << endl;delete _ptr;}}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};
}
std::shared_ptr
C++11中开始提供更靠谱的并且支持拷贝的shared_ptr 。
#include <memory>
#include <iostream>class A
{
public:~A(){std::cout << "~A()" << std::endl;}int _a1 = 0;int _a2 = 0;
};void test_shared_ptr()
{std::shared_ptr<A> sp1(new A);std::shared_ptr<A> sp2(sp1);sp1->_a1++;sp1->_a2++;std::cout << sp2->_a1 << ":" << sp2->_a2 << std::endl;sp2->_a1++;sp2->_a2++;std::cout << sp1->_a1 << ":" << sp1->_a2 << std::endl;
}int main()
{test_shared_ptr();return 0;
}
- shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享。
- 在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减一。
- 如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;
- 如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。
std::shared_ptr的模拟实现
不能用static修饰计数器,因为这样会让所有的模拟实现的shared_ptr的不同类型的实例化,同用一个计数器。需要的是一个资源,配一个计数器,多个智能指针对象共管静态计数对象,所以资源都只有一个计数,因为静态成员属于整个类,属于类的所有对象。
所以使用的是一个指针,这个时候这个指针指向的空间就是new出来的,使用构造函数new,这就保证了同一个资源,用一个计数器。并且这样这个指针就会指向需释放的资源,也指向了计数。
即:每个资源需要管理的时候,会给构造函数,构造new一个计数。
namespace cr
{template<class T>class shared_ptr{public:shared_ptr(T* ptr = nullptr): _ptr(ptr), _pCount(new int(1)){}// 判断是否释放void Release(){// 减减被赋值对象的计数,如果是最后一个对象,要释放资源if (--(*_pCount) == 0){cout << "Delete:" << _ptr << endl;delete _ptr;delete _pCount;}}~shared_ptr(){Release();}// sp1(sp2)shared_ptr(const shared_ptr<T>& sp): _ptr(sp._ptr), _pCount(sp._pCount){(*_pCount)++;}shared_ptr<T>& operator=(const shared_ptr<T>& sp){// 防止自己给自己赋值,导致计数--,出现内存泄漏if (_ptr == sp._ptr){return *this;}// 判断是否释放 -- 防止_ptr原来的数据未计数--,导致内存泄漏Release();// 共管新资源,++计数_ptr = sp._ptr;_pCount = sp._pCount;(*_pCount)++;return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;// 引用计数int* _pCount;};
}
shared_ptr看起来很完美,但是也有问题:
- 在多线程使用shared_ptr的时候,shared_ptr不是线程安全的。
- shared_ptr存在一个循环引用的问题。
循环引用问题
(是一个非常特殊的情况下)
#include <iostream>
#include <memory>class Node
{
public:~Node(){std::cout << "~Node" << std::endl;}int val = 0;std::shared_ptr<Node> _next;std::shared_ptr<Node> _prev;
};void test_shared_ptr()
{std::shared_ptr<Node> s1(new Node);std::shared_ptr<Node> s2(new Node);s1->_next = s2;s2->_prev = s1;
}int main()
{test_shared_ptr();return 0;
}
我们可以发现上面代码并没有像我们想象的一样,自动调用析构函数:
分析:
当下图的时候,是没有问题的,也就是对于shared_ptr智能指针的使用,shared_ptr的计数器分别都++。
但是当继续向下执行的时候,就是问题的关键所在。
此处:shared_ptr类型的s1,经过operator ->的重载,于是变为(Node*)->_next = s2,此处Note中的_next对象是shared_ptr类型的,所以会调用s2中的智能指针的赋值。
同理:会调用s1中的智能指针的赋值。
于是s1与s2的计数器分别都++到了2。
#问:通过以上为什么不会调用析构?
因为,根据函数的创建顺序,s2后构造所以先析构,s1先构造所以后析构。
于是s2与s1就分别调用它们的析构函数了,于是计数器分别都--到了1。但是由于:
- _next:管着右边的节点内存块。
- _prev:管着左边的节点内存块。
于是,便出现:理想状态下,_next释放那右边就释放,_prev释放那左边就释放。
但是会出现一个问题,_next与_prev分别数据不同的成员节点,对于对象中的成员是需要该对象调用析构函数才会释放其中的成员,于是对于左节点是需要计数器--到0,才能释放左节点,_next才会析构。同样的,右节点是需要计数器--到0,才会释放右节点,_prev才会析构。
这就是一个死循环,所以没有调用Node的析构函数,也就不可能看到Node类型对象的析构释放显示。
解决方式:
这个地方想使用shared_ptr进行Node类型的对象中类似的操作是把必定错的,没有办法,所以C++也为我们提供了一个新的方式:weak_ptr(弱指针)
weak_ptr与其他的智能指针都不一样,其并不是常规智能指针,没有RAII,不支持直接管理资源。weak_ptr主要用shared_ptr构造,用来解决shared_ptr循环引用问题。
https://legacy.cplusplus.com/reference/memory/weak_ptr/?kw=weak_ptr
主要用share_ptr来构造自己,并不支持用一个资源构造自己,所以其并不支持RAII。
- 特点:不++share_ptr的计数器。
#include <iostream>
#include <memory>class Node
{
public:~Node(){std::cout << "~Node" << std::endl;}int val = 0;std::weak_ptr<Node> _next;std::weak_ptr<Node> _prev;
};void test_shared_ptr()
{std::shared_ptr<Node> s1(new Node);std::shared_ptr<Node> s2(new Node);s1->_next = s2;s2->_prev = s1;
}int main()
{test_shared_ptr();return 0;
}
当 _next 与 _prev 是 weak_ptr 的时候,它们不参加资源的释放管理,但是可以访问和修改数据,且并不增加计数,所以不会存在循环引用的问题了。(这个方法可行,但是因为不计数,多以我们要识别到这个问题)
Note:
想看到计数的对应变化,可以使用shared_ptr的成员函数 use_count 。
weak_ptr的模拟实现
对于前面所模拟实现的shared_ptr同样的也具有循环引用的问题。
#include <iostream>namespace cr
{template<class T>class shared_ptr{public:shared_ptr(T* ptr = nullptr): _ptr(ptr), _pCount(new int(1)){}// 判断是否释放void Release(){// 减减被赋值对象的计数,如果是最后一个对象,要释放资源if (--(*_pCount) == 0){delete _ptr;delete _pCount;}}~shared_ptr(){Release();}// sp1(sp2)shared_ptr(const shared_ptr<T>& sp): _ptr(sp._ptr), _pCount(sp._pCount){(*_pCount)++;}shared_ptr<T>& operator=(const shared_ptr<T>& sp){// 防止自己给自己赋值,导致计数--,出现内存泄漏if (_ptr == sp._ptr)return *this;// 判断是否释放 -- 防止_ptr原来的数据未计数--,导致内存泄漏Release();// 共管新资源,++计数_ptr = sp._ptr;_pCount = sp._pCount;(*_pCount)++;return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;// 引用计数int* _pCount;};
}class Node
{
public:~Node(){std::cout << "~Node" << std::endl;}int val = 0;cr::shared_ptr<Node> _next;cr::shared_ptr<Node> _prev;
};void test_shared_ptr()
{cr::shared_ptr<Node> s1(new Node);cr::shared_ptr<Node> s2(new Node);s1->_next = s2;s2->_prev = s1;
}int main()
{test_shared_ptr();return 0;
}
于是可以通过模拟实现weak_ptr进行避免我们所模拟实现的shared_ptr,出现循环引用的问题。
#include <iostream>namespace cr
{template <class T>class shared_ptr{public:shared_ptr(T *ptr = nullptr) : _ptr(ptr), _pCount(new int(1)) {}// 判断是否释放void Release(){// 减减被赋值对象的计数,如果是最后一个对象,要释放资源if (--(*_pCount) == 0){delete _ptr;delete _pCount;}}~shared_ptr() { Release(); }// sp1(sp2)shared_ptr(const shared_ptr<T> &sp) : _ptr(sp._ptr), _pCount(sp._pCount) { (*_pCount)++; }shared_ptr<T> &operator=(const shared_ptr<T> &sp){// 防止自己给自己赋值,导致计数--,出现内存泄漏if (_ptr == sp._ptr)return *this;// 判断是否释放 -- 防止_ptr原来的数据未计数--,导致内存泄漏Release();// 共管新资源,++计数_ptr = sp._ptr;_pCount = sp._pCount;(*_pCount)++;return *this;}T &operator*() { return *_ptr; }T *operator->() { return _ptr; }// 便于外部获取ptr,如weak_ptrT *get()const{return _ptr;}private:T *_ptr;// 引用计数int *_pCount;};// 辅助型智能指针,使命配合解决shared_ptr循环引用问题template <class T>class weak_ptr{public:weak_ptr(): _ptr(nullptr){}weak_ptr(const shared_ptr<T> &sp): _ptr(sp.get()){}weak_ptr(const weak_ptr<T> &wp): _ptr(wp._ptr){}weak_ptr<T>& operator=(const shared_ptr<T>& sp){_ptr = sp.get();return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T *_ptr;};
}class Node
{
public:~Node() { std::cout << "~Node" << std::endl; }int val = 0;cr::weak_ptr<Node> _next;cr::weak_ptr<Node> _prev;
};void test_shared_ptr()
{cr::shared_ptr<Node> s1(new Node);cr::shared_ptr<Node> s2(new Node);s1->_next = s2;s2->_prev = s1;
}int main()
{test_shared_ptr();return 0;
}
需要掌握:
- 为什么需要智能指针?
主要的原因还是因为内存泄漏:忘记释放的问题,更重要还有异常安全的问题。
- RAII?
资源获得,资源请求机立即初始化。指的就是把资源交给一个对象,利用构造将其资源交给一个对象去管理。
- 发展历史
- auto_ptr / unique_ptr / shared_ptr / weak_ptr之间的区别与使用场景。
- 模拟实现简洁版智能指针。
- 什么是循环引用?如何解决循环引用?解决的原理是什么?
相关文章:

【C++】-- 智能指针
目录 智能指针意义 智能指针的使用及原理 RAII 智能指针的原理 std::auto_ptr std::auto_ptr的模拟实现 std::unique_ptr std::unique_ptr模拟实现 std::shared_ptr std::shared_ptr的模拟实现 循环引用问题 智能指针意义 #问:为什么需要智能指针&#…...

数据结构与算法——4时间复杂度分析2(常见的大O阶)
这篇文章是时间复杂度分析的第二篇。在前一篇文章中,我们从0推导出了为什么要用时间复杂度,时间复杂度如何分析以及时间复杂度的表示三部分内容。这篇文章,是对一些常用的时间复杂度进行一个总结,相当于是一个小结论 1.常见的大O…...

IIS解析漏洞
IIS 6.0在解析文件时存在以下两个解析漏洞。 ①当建立*.asa、*.asp格式的文件夹时,其目录下的任意文件都将被IIS当作asp文件来解析。 例如:建立文件夹 parsing.asp,在 parsing.asp 文件夹内新建一个文本文档 test.txt,其内容为&…...

2023 年腾讯云轻量和CVM服务器租用价格表出炉(CPU/内存/带宽/系统盘)
腾讯云服务器的价格表是用户比较关心的问题,服务器的价格组成包括云服务器的机型价格、磁盘价格和宽带价格,主机教程网来详细说下腾讯云最新的云服务器价格表。我们以北京一区、Linux系统的云服务器为例,其他地域的价格会有所差异,…...

Java学习之路002——面向对象编程
【说明】部分内容来源于网络,如有冲突,请联系作者删除。 一、面向对象编程(OOP) 2.1 对象和类的关系 2.2 面向对象的特征 2.2.1 封装 2.2.2 继承 2.2.3 多态 3、抽象 使用abstract关键字修饰的类或者方法 定义抽象类(使用abstract) // 1、定义抽象方法…...

VR直播丨颠覆性技术革命,新型直播已经到来
细数当下最火热的营销手段,首先浮现脑海的无疑是“直播”。前有罗永浩、李佳琦,后有刘畊宏和东方甄选,直播如日中天,俨然成了大众足不出户就能休闲娱乐的重要途径。 而随着虚拟现实在“十四五规划”中被列入“建设数字中国”数字…...

【微信小程序】-- WXSS 模板样式- rpx import (十三)
💌 所属专栏:【微信小程序开发教程】 😀 作 者:我是夜阑的狗🐶 🚀 个人简介:一个正在努力学技术的CV工程师,专注基础和实战分享 ,欢迎咨询! &…...

Biotin-PEG-SVA,生物素聚乙二醇琥珀酰亚胺戊酸酯,可用于检测或分子标记
Biotin-PEG-SVA 结构式:PEG分子量: 1000,2000,3400,5000,10000中文名称:生物素聚乙二醇琥珀酰亚胺戊酸酯,生物素-PEG-琥珀酰亚胺戊酸酯英文名称:Biotin-PEG-SVA …...

云原生是什么?核心概念和应用方法解析
什么是云原生? 云原生是一种基于容器、微服务和自动化运维的软件开发和部署方法。它可以使应用程序更加高效、可靠和可扩展,适用于各种不同的云平台。 如果要更直接通俗的来解释下上面的概念。云原生更准确来说就是一种文化,是一种潮流&…...

Editor工具开发实用篇:EditorGUI/EditorGUILayout的区别和EditorGUILayout的方法介绍
目录 一:EditorGUI和EditorGUILayout区别 二:EditorGUILayout 1.EditorGUILayout.BeginFadeGroup(float value); 2.EditorGUILayout.BeginHorizontal EditorGUILayout.BeginVertical 3.EditorGUILayout.BeginScrollView 4.EditorGUILayout.BeginT…...

(五十二)大白话不断在表中插入数据时,物理存储是如何进行页分裂的?.md
上回我们讲到了数据页的物理存储结构,数据页之间是组成双向链表的,数据页内部的数据行是组成单向链表的,每个数据页内根据主键做了一个页目录 然后一般来说,你没有索引的情况下,所有的数据查询,其实在物理…...

Unity 渲染顺序
Unity中的渲染顺序自上而下大致分为三层渲染优先级 Camera depth > Sorting Layer > Order in Layer > RenderQueueCamera depth:越小越优先(大的显示在小的前面)如图:尽管Sphere距离摄像机较远,但由于Camera_Sphere dep…...

短视频美颜sdk人脸编辑技术详解、美颜sdk代码分析
短视频美颜sdk中人脸编辑技术可以将人像风格进行转变,小编认为这也是未来的美颜sdk的一个重要发展方向,下文小编将为大家讲解一下短视频美颜sdk中人脸编辑的关键点。 一、人脸编辑的细分关键点 1、年龄 通过更改人脸的年龄属性,可用于模仿人…...

error: expected declaration specifiers or ‘...’ before ‘(’ token
一、问题 最近写函数时,遇到了一个比较奇怪的问题,相信也好多人遇到一下的问题: error: expected declaration specifiers or ‘...’ before ‘(’ token代码如下: #include<stdio.h> struct stu{char *name;int score;…...

系列七、索引
一、索引概述 1.1、概述 索引(index)是帮助MySQL高效获取数据的数据结构(有序)。在数据之外,数据库系统还维护着满足特定查找算法的数据结构,这些数据结构以某种方式引用(指向)数据, 这样就可以…...

Java开发 - Elasticsearch初体验
目录 前言 什么是es? 为什么要使用es? es查询的原理? es需要准备什么? es基本用法 创建工程 添加依赖 创建操作es的文件 使用ik分词插件 Spring Data 项目中引入Spring Data 添加依赖 添加配置 创建操作es的业务逻…...

mysql进阶
mysql进阶视图视图是一个基于查询的虚拟表,封装了一条sql语句,通俗的解释,视图就是一条select查询之后的结果集,视图并不存储数据,数据仍旧存储在表中。创建视图语句:create view view_admin as select * from admin使…...

SD卡损坏了?储存卡恢复数据就靠这3个方法
作为一种方便的储存设备,SD卡在我们的日常生活中使用非常广泛。但是,有时候我们可能会遇到SD卡损坏的情况,这时候里面存储的数据就会受到影响。SD卡里面保存着我们很多重要的数据,有些还是工作必须要使用的。 如果您遇到了这种情…...

springboot+实践(总结到位)
一。【SpringBoot注解-1】 牛逼:云深i不知处 【SpringBoot注解-1】:常见注解总览_云深i不知处的博客-CSDN博客 二。【SpringBoot-3】Lombok使用详解 【SpringBoot-3】Lombok使用详解_云深i不知处的博客-CSDN博客_springboot lombok 三࿰…...

CorelDRAW2023新功能有哪些?最新版cdr下载安装教程
使用 CorelDRAW2023,随时随都能进行设计创作。在 Windows或Mac上使用专为此平台设计的直观界面,以自己的风格尽情自由创作。同全球数百万信赖CorelDRAW Graphics Suite 的艺术家、设计者及小型企业主一样,大胆展现真我,创作出众的…...

PLC 程序设计标准化方法
PLC 程序设计的标准化方法先从内容或者方法层面进行流程的分解,将分解的内容称为要素,要素的有机结合便构成了标准化的设计。流程标准化设计完成之后需要对各个要素分别进行标准化的设计。2.1、 PLC 程序设计的要素分解与有机结合根据软件程序设计的一般性方法结合PLC 程序设计…...

设计模式-笔记
文章目录七大原则单例模式桥模式 bridge观察者模式 observer责任链模式 Chain of Responsibility命令模式 Command迭代器模式 Iterator中介者模式 Mediator享元模式 Flyweight Pattern组合模式 composite装饰模式 Decorator外观模式 Facade简单工厂模式工厂方法模式工厂抽象模式…...

【全志T113-S3_100ask】12-3 Linux蓝牙通信实战(基于BlueZ的C语言BLE蓝牙编程)
【全志T113-S3_100ask】12-3 Linux蓝牙通信实战(基于BlueZ的C语言BLE蓝牙编程 背景(一)获取BlueZ源码(二)首次编译2-1 编写Makefile2-2 make编译2-3 首次测试2-3-1 开发板操作2-3-2 安卓端操作(三)源码分析3-1 程序入口3-2 蓝牙设备名称3-3 GATT服务(四)实战4-1 添加B…...

Java学习之路003——集合
1、 代码演示 【1】新增一个类,用来测试集合。先创建一组数组,数组可以存放不同的数据类型。对于Object类型的数组元素,可以通过.getClass方法获取到具体类型。 【2】如果数组指定类型为int的时候,使用.getClass()就会提示错误。 …...

生成和查看dump文件
在日常开发中,即使代码写得有多谨慎,免不了还是会发生各种意外的事件,比如服务器内存突然飙高,又或者发生内存溢出(OOM)。当发生这种情况时,我们怎么去排查,怎么去分析原因呢? 1. 什么是dump文…...

K8S集群1.24使用docker作为容器运行时出现就绪探针间歇性异常
文章目录1. 环境介绍2. 异常信息3. 分析问题3.1 kubernetes 健康检查3.1.1 存活探针3.1.2 就绪探针3.1.3 启动探针3.2 检测方法4. 解决办法1. 环境介绍 组件版本kubernetes1.24.2docker18.03.1-cecri-docker0.2.6 2. 异常信息 最近监测到 kubernetes 集群上 calico-node Pod 运…...

士大夫身份第三方水电费第三方
package com.snmocha.snbpm.job;import org.springframework.stereotype.Component;import com.xxl.job.core.handler.annotation.XxlJob;import lombok.extern.slf4j.Slf4j;/*** Demo定时任务.* Author:zhoudd* Date:2023-01-15*/ Component Slf4j publ…...

RDO一体化部署OpenStack
RDO一体化部署OpenStack 环境准备 安装centos7 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-J785hZvT-1677578418769)(C:\Users\HONOR\AppData\Roaming\Typora\typora-user-images\image-20230228171254675.png)] 使用vmware安装安装centos7&a…...

CC2530+ESP8266使用MQTT协议上传阿里云的问题
ATMQTTPUB<LinkID>,<"topic">,<"data">,<qos>,<retain>LinkID: 当前只支持 0 topic: 发布主题, 最长 64 字节 data: 发布消息, data 不能包含 \0, 请确保整条 ATMQTTPUB 不超过 AT 指令的最大长度限制 qos: 发布服务质量, 参…...

Java基础:爬虫
1.本地爬虫 Pattern:表示正则表达式 Matcher:文本匹配器,作用按照正则表达式的规则去读取字符串,从头开始读取。在大串中去找符合匹配规则的子串。 1.2.获取Pattern对象 通过Pattern p Pattern.compile("正则表达式");获得 1.3.获取Matc…...