C++进阶——C++11_智能指针
目录
1、问题引入
2、RAII和智能指针
3、C++标准库的智能指针
3.1 auto_ptr (不好)
3.2 unique_ptr
3.4 weak_ptr (重点)
6、C++11智能指针和boost的关系
7、内存泄漏
7.1 什么是内存泄漏,内存泄漏的危害
7.2 如何避免内存泄漏
1、问题引入
下面的程序中我们可以看到,new了以后,我们也delete了,
但是如果抛出异常导致后面的delete没有得到执行,所以就内存泄漏了。所以我们需要在new以后捕获异常,捕获到异常后delete,再把异常抛出,
但是new本身也可能会抛出异常,如果int* array2 = new int[10];时抛出异常,需要捕获异常,delete array1,再重新抛出,
由于try块通常捕获单一类型的异常,那么就需要多个try块,可能还要捕获,抛出,比较麻烦。
注意:都是资源泄漏的问题。
#include <iostream>
#include <exception>using namespace std;double Divide(int a, int b)
{// 当b == 0时抛出异常if (b == 0){throw "Divide by zero condition!";}return (double)a / (double)b;
}void Func()
{// 原始内存分配int* array1 = new int[10];int* array2 = new int[10]; // 这里可能抛出bad_alloc异常try{int len, time;cin >> len >> time;cout << Divide(len, time) << endl;}catch (...){// 异常处理中释放内存cout << "delete []" << array1 << endl;delete[] array1;cout << "delete []" << array2 << endl;delete[] array2;throw; // 重新抛出异常}// 正常流程释放内存cout << "delete []" << array1 << endl;delete[] array1;cout << "delete []" << array2 << endl;delete[] array2;
}int main()
{try{Func();}catch (const char* errmsg) // 捕获字符串异常{cout << errmsg << endl;}catch (const exception& e) // 捕获标准异常{cout << e.what() << endl;}catch (...) // 捕获其他所有异常{cout << "未知异常" << endl;}return 0;
}
2、RAII和智能指针
RAII (资源获取立即初始化)是 Resource Acquisition Is Initialization 的缩写,它是一种管理资源的类的设计思想,这里的资源可以是内存、文件指针、网络连接、互斥锁等等。
RAII 的核心思想: 创建对象时就完成资源的获取操作,并且在对象的生命周期内持有该资源。当对象的生命周期结束,其所持有的资源会被自动释放(析构)。这样就把资源的管理和对象的生命周期紧密绑定起来。保障了资源的正常释放,避免资源泄漏问题。
智能指针类除了满足 RAII 的设计思想,
还会像迭代器类一样,重载 operator*/operator->/operator [] 等运算符,方便访问资源。
#include <iostream>
#include <exception>using namespace std;template<class T>
class SmartPtr
{
public:// RAII 构造函数SmartPtr(T* ptr):_ptr(ptr){}// 析构函数自动释放资源~SmartPtr(){cout << "delete[] " << _ptr << endl;delete[] _ptr;}// 重载运算符,模拟指针行为T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T& operator[](size_t i){return _ptr[i];}private:T* _ptr;
};double Divide(int a, int b)
{// 当 b == 0 时抛出异常if (b == 0){throw "Divide by zero condition!";}return (double)a / (double)b;
}void Func()
{// 使用 RAII 的智能指针类管理数组SmartPtr<int> sp1 = new int[10];SmartPtr<int> sp2 = new int[10];// 初始化数组for (size_t i = 0; i < 10; i++){sp1[i] = sp2[i] = i;}int len, time;cin >> len >> time;cout << Divide(len, time) << endl;
}int main()
{try{Func();}catch (const char* errmsg){cout << errmsg << endl;}catch (const exception& e){cout << e.what() << endl;}catch (...){cout << "未知异常" << endl;}return 0;
}
3、C++标准库的智能指针
C++标准库中的智能指针都在头文件<memory>里面。
3.1 auto_ptr (不好)
auto_ptr 是C++98时设计出来的智能指针,
拷贝时把被拷贝对象的资源的管理权 转移给 拷贝对象(即始终只有一个对象管理资源),这是一个非常糟糕的设计,因为他会导致被拷贝对象悬空,访问报错的问题。C++11设计出新的智能指针后,强烈建议不要使用auto_ptr。其他C++11出来之前很多公司也是明令禁止使用这个智能指针的。
简单模拟实现:
template<class T>
class auto_ptr
{
public:// 构造函数auto_ptr(T* ptr):_ptr(ptr){}// 拷贝构造函数(管理权转移)auto_ptr(auto_ptr<T>& sp):_ptr(sp._ptr){sp._ptr = nullptr; // 转移后置空原指针}// 赋值运算符重载auto_ptr<T>& operator=(auto_ptr<T>& ap){// 检测自赋值if (this != &ap){// 释放当前资源if (_ptr)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; // 原始指针
};
3.2 unique_ptr
unique_ptr 是C++11设计出来的智能指针。翻译为唯一指针。
不支持拷贝,只支持移动。如果不需要拷贝的场景就非常建议使用他。
简单模拟实现:
template<class T>
class unique_ptr
{
public:// explicit 防止隐式转换explicit unique_ptr(T* ptr): _ptr(ptr){}// 析构函数(自动释放资源)~unique_ptr(){if (_ptr){cout << "delete:" << _ptr << endl;delete _ptr;}}// 禁用拷贝构造和拷贝赋值(=delete)unique_ptr(const unique_ptr<T>& sp) = delete;unique_ptr<T>& operator=(const unique_ptr<T>& sp) = delete;// 移动构造函数(转移所有权)unique_ptr(unique_ptr<T>&& sp): _ptr(sp._ptr){sp._ptr = nullptr;}// 移动赋值运算符(转移所有权)unique_ptr<T>& operator=(unique_ptr<T>&& sp){if (this != &sp) // 防止自移动{delete _ptr; // 释放当前资源_ptr = sp._ptr; // 接管新资源sp._ptr = nullptr;}return *this;}// 重载指针操作符T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr; // 管理的原始指针
};
3.3 shared_ptr (重点)
shared_ptr 是C++11设计出来的智能指针,支持拷贝,也支持移动。翻译为共享指针。
如果需要拷贝的场景就非常建议使用他了。底层是用引用计数的方式实现的。
简单模拟实现:
template <class T>
class shared_ptr
{
public:// explicit 防止隐式转换explicit shared_ptr(T* ptr):_ptr(ptr): _pcount(new int(1)){}~shared_ptr(){if (--(*_pcount) == 0){delete _ptr;delete _pcount;_ptr = _pcount = nullptr;}}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){if (--(*_pcount) == 0){delete _ptr;delete _pcount;_ptr = _pcount = nullptr;}_ptr = sp._ptr;_pcount = sp._pcount;++(*_pcount);}return *this;}T& operator*() const{return *_ptr;}T* operator->() const{return _ptr;}int use_pcount() const{return *_pcount;}T* get_ptr() const{return _ptr;}private:T* _ptr;int* _pcount;
};
注意:
1. 释放资源可能不匹配:
如果是new,就delete,如果是new [ ],就delete[ ],匹配使用,而且可能是FILE*类型的指针,不能delete, 应该是fclose。
解决方案:构造函数写成模板,传定制删除器。
定制删除器默认是delete,由于delete[ ]也比较常用,所以库里面特化了delete[ ]的版本(不用自己传delete[ ]定制删除器)。
shared_ptr一般传lambda表达式,更方便。如:
std::shared_ptr<Date[]> sp2(new Date[10]); // 特化
std::shared_ptr<Date> sp3(new Date[10], [](Date* ptr) {delete[] ptr; });
unique_ptr也传定制删除器,不过是在unique_ptr的模板参数传(传仿函数类型更方便)。如:
class Fclose
{
public:void operator()(FILE* ptr){cout << "fclose:" << ptr << endl;fclose(ptr);}
};std::unique_ptr<FILE, Fclose> up1(fopen("Test.cpp", "r"));
std::unique_ptr<Date[]> up2(new Date[10]); // 特化
所以:
#include <functional>namespace Lzc
{template <class T>class shared_ptr{public:// explicit 防止隐式转换explicit shared_ptr(T* ptr):_ptr(ptr): _pcount(new int(1)){}template<class D>explicit shared_ptr(T* ptr, D del):_ptr(ptr): _pcount(new int(1)): _del(del){}~shared_ptr(){if (--(*_pcount) == 0){_del(_ptr);delete _pcount;_ptr = _pcount = nullptr;}}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){if (--(*_pcount) == 0){_del(_ptr);delete _pcount;_ptr = _pcount = nullptr;}_ptr = sp._ptr;_pcount = sp._pcount;++(*_pcount);}return *this;}T& operator*() const{return *_ptr;}T* operator->() const{return _ptr;}int use_pcount() const{return *_pcount;}T* get_ptr() const{return _ptr;}private:T* _ptr;int* _pcount;function<void(T*)> _del = [](T* ptr) {delete ptr; };};
}
2.
template <class T, class... Args> shared_ptr<T> make_shared(Args&&... args);
std::shared_ptr<Date> sp1(new Date(2024, 9, 11));
std::shared_ptr<Date> sp2 = std::make_shared<Date>(2024, 9, 11);
区别就是,将资源和引用计数的空间一起开,减少空间碎片。
3. unique_ptr和shared_ptr都支持 operator bool 的类型转换,如果智能指针对象是一个空对象没有管理资源,则返回 false,否则返回 true,意味着可以直接用 if 判断是否为空。
4. unique_ptr和shared_ptr的构造函数都使用 explicit 修饰,防止普通指针隐式类型转换成智能指针对象。
3.4 weak_ptr (重点)
weak_ptr 是C++11设计出来的智能指针。翻译为弱指针。
不能单独管理资源(只能绑定share_ptr的资源),不增加对象的引用计数,主要用于解决 shared_ptr 循环引用造成的内存泄漏的问题。
weak_ptr也没有重载operator*和operator->等,不直接访问资源。
简单模拟实现:
// 需要注意的是我们这里实现的 shared_ptr 和 weak_ptr 都是以最简洁的方式实现的,
// 只能满足基本的功能,这里的 weak_ptr lock 等功能是无法实现的,想要实现就要
// 把 shared_ptr 和 weak_ptr 一起改了,把引用计数拿出来放到一个单独类型,
// shared_ptr 和 weak_ptr 都要存储指向这个类的对象才能实现,有兴趣可以去翻翻源代码template<class T>
class weak_ptr
{
public:weak_ptr() {}weak_ptr(const shared_ptr<T>& sp): _ptr(sp.get()){}weak_ptr<T>& operator=(const shared_ptr<T>& sp){_ptr = sp.get();return *this;}private:T* _ptr = nullptr;
};
注意:
如果weak_ptr绑定的 shared_ptr已经释放了资源,那么weak_ptr去访问资源就是很危险的。
weak_ptr支持expired检查指向的资源是否过期。过期返回true,否则返回false。
use_count也可获取shared_ptr的引用计数(这里如果shared_ptr的引用计数为0,就不能立即释放,还需要一个引用计数,判断是否还有weak_ptr指向)。expired即use_count() == 0。
weak_ptr可以调用 lock 返回一个管理资源的shared_ptr,如果资源已经被释放,返回的shared_ptr是一个空对象,如果资源没有释放,则通过返回的shared_ptr访问资源是安全的。
#include <iostream>
#include <memory>
#include <string>using namespace std;int main() {// 初始化共享指针和弱指针shared_ptr<string> sp1(new string("111111"));shared_ptr<string> sp2(sp1);weak_ptr<string> wp = sp1;// 检查弱指针状态cout << "Initial state:" << endl;cout << "wp.expired(): " << wp.expired() << endl; // 0 (未过期)cout << "wp.use_count(): " << wp.use_count() << endl; // 2 (sp1和sp2)// sp1指向新资源sp1 = make_shared<string>("222222");cout << "\nAfter sp1 reassignment:" << endl;cout << "wp.expired(): " << wp.expired() << endl; // 0 (sp2仍持有)cout << "wp.use_count(): " << wp.use_count() << endl; // 1 (仅sp2)// sp2指向新资源sp2 = make_shared<string>("333333");cout << "\nAfter sp2 reassignment:" << endl;cout << "wp.expired(): " << wp.expired() << endl; // 1 (已过期)cout << "wp.use_count(): " << wp.use_count() << endl; // 0// 重新绑定弱指针wp = sp1;auto sp3 = wp.lock(); // 提升为共享指针*sp3 += "###";cout << "\nAfter reusing wp:" << endl;cout << "wp.expired(): " << wp.expired() << endl; // 0cout << "wp.use_count(): " << wp.use_count() << endl; // 2 (sp1和sp3)// 输出最终内容cout << "\nFinal string: " << *sp1 << endl;return 0;
}
4、shared_ptr的循环引用问题(重点)
#include <iostream>
#include <memory>struct ListNode {int _data;/*ListNode* _next;ListNode* _prev;*//*std::shared_ptr<ListNode> _next;std::shared_ptr<ListNode> _prev;*/// 这里改成weak_ptr,当n1->_next = n2;绑定shared_ptr时// 不增加n2的引用计数,不参与资源释放的管理,就不会形成循环引用了std::weak_ptr<ListNode> _next;std::weak_ptr<ListNode> _prev;~ListNode() {std::cout << "~ListNode()" << std::endl;}
};int main() {// 循环引用 -- 内存泄露std::shared_ptr<ListNode> n1(new ListNode);std::shared_ptr<ListNode> n2(new ListNode);std::cout << n1.use_count() << std::endl;std::cout << n2.use_count() << std::endl;n1->_next = n2;n2->_prev = n1;std::cout << n1.use_count() << std::endl;std::cout << n2.use_count() << std::endl;return 0;
}
所以也可以用weak_ptr拷贝构造shared_ptr。
5、shared_ptr的线程安全问题
shared_ptr的引用计数对象在堆上,如果多个shared_ptr对象在多个线程中,进行shared_ptr的拷贝析构或析构时会修改引用计数,就会存在线程安全问题,所以shared_ptr引用计数是需要加锁或者原子操作保证线程安全的。
shared_ptr指向的对象也是有线程安全的问题的,但是这个对象的线程安全问题不归shared_ptr管,它也管不了,应该有外层使用shared_ptr的人进行线程安全的控制。
下面的程序会崩溃或者A资源没释放,
原子操作:shared_ptr引用计数从int*改成atomic<int>*就可以保证引用计数的线程安全,或者使用互斥锁加锁也可以。
#include <functional>
#include<atomic>namespace Lzc
{template <class T>class shared_ptr{public:// explicit 防止隐式转换explicit shared_ptr(T* ptr):_ptr(ptr): _pcount(new atomic<int>(1)){}template<class D>explicit shared_ptr(T* ptr, D del):_ptr(ptr): _pcount(new atomic<int>(1)): _del(del){}~shared_ptr(){if (--(*_pcount) == 0){_del(_ptr);delete _pcount;_ptr = _pcount = nullptr;}}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){if (--(*_pcount) == 0){_del(_ptr);delete _pcount;_ptr = _pcount = nullptr;}_ptr = sp._ptr;_pcount = sp._pcount;++(*_pcount);}return *this;}T& operator*() const{return *_ptr;}T* operator->() const{return _ptr;}int use_pcount() const{return *_pcount;}T* get_ptr() const{return _ptr;}private:T* _ptr;// int* _pcount;atomic<int>* _pcount; // 原子操作function<void(T*)> _del = [](T* ptr) {delete ptr; };};
}
struct AA {int _a1 = 0;int _a2 = 0;~AA() {cout << "~AA()" << endl;}
};int main() {Lzc::shared_ptr<AA> p(new AA); // 原始智能指针const size_t n = 100000; // 每个线程的循环次数mutex mtx; // 用于保护共享数据访问// 线程函数(lambda表达式)auto func = [&]() {for (size_t i = 0; i < n; ++i) {// 拷贝构造会递增引用计数Lzc::shared_ptr<AA> copy(p);{// 加锁保护AA对象成员的修改unique_lock<mutex> lk(mtx);copy->_a1++;copy->_a2++;}}};// 创建并启动两个线程thread t1(func);thread t2(func);// 等待线程结束t1.join();t2.join();// 输出最终结果cout << "Final _a1: " << p->_a1 << endl;cout << "Final _a2: " << p->_a2 << endl;cout << "Final use_count: " << p.use_count() << endl;return 0;
}
6、C++11智能指针和boost的关系
Boost库是为C++语言标准库提供扩展的一些C++程序库的总称,Boost社区建立的初衷之一就是为C++的标准化工作提供可供参考的实现,Boost社区的发起人Dawes本人就是C++标准委员会的成员之一。在Boost库的开发中,Boost社区也在这个方向上取得了丰硕的成果,C++11及之后的新语法和库有很多都是从Boost中来的。
C++98中产生了第一个智能指针auto_ptr。
C++ boost给出了更实用的scoped_ptr/scoped_array和shared_ptr/shared_array和weak_ptr等。
C++ TR1,引入了shared_ptr等,不过注意的是TR1并不是标准版。
C++11,引入了unique_ptr和shared_ptr和weak_ptr。需要注意的是unique_ptr对应boost的scoped_ptr。并且这些智能指针的实现原理是参考boost中的实现的。
7、内存泄漏
7.1 什么是内存泄漏,内存泄漏的危害
什么是内存泄漏:内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存,一般是忘记释放或者发生异常释放程序未能执行导致的。内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。
内存泄漏的危害:普通程序运行一会就结束了出现内存泄漏问题也不大,进程正常结束,页表的映射关系解除,物理内存也可以释放。长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务、长时间运行的客户端等等,不断出现内存泄漏会导致可用内存不断变少,各种功能响应越来越慢,最终卡死。
7.2 如何避免内存泄漏
正确使用智能指针+定期检测。
相关文章:
C++进阶——C++11_智能指针
目录 1、问题引入 2、RAII和智能指针 3、C标准库的智能指针 3.1 auto_ptr (不好) 3.2 unique_ptr 3.3 shared_ptr (重点) 3.4 weak_ptr (重点) 4、shared_ptr的循环引用问题(重点) 5、shared_ptr的线程安全问题 6、C11智能指针和boost的关系 7、内存泄漏 7.1 什么是…...
音频格式转换
1. 下载ffmpeg https://www.gyan.dev/ffmpeg/builds/packages/ffmpeg-7.1.1-full_build.7z 2. 配置ffmpeg环境变量 3.安装pydub pip install pydub 4.编写转化工具代码 from pydub import AudioSegment def convertM4aToWav(m4a,wav):sound AudioSegment.from_file(m4a, f…...
mysql安装配置教程
由于您可能需要针对特定操作系统(如Windows、macOS或Linux)的MySQL安装配置教程,这里我将提供一个较为通用的指南,适用于大多数情况。如果您有特定的操作系统需求,请告诉我,我可以提供更详细的指导。 ### …...
埃文科技助力山西公共数据运营新发展
近日,郑州埃文科技有限公司(以下简称“埃文科技”)凭借“数据场景生态”的三维核心竞争力,成为山西云时代政务云技术有限公司专业领域数据类产品授权运营合作伙伴。 埃文科技作为数据全生命周期价值建设先行者,深度赋…...
【STM32】在FreeRTOS下使用硬件SPI收发数据出现的时序耦合问题(WK2124芯片为例)
问题 STM32中在Freertos使用SPI通讯芯片 WK2124进行SPI转4串口时,接收数据为一个任务,发送数据为一个任务,切接受任务优先级更高实测发现收发一段时间(约几分钟)外扩芯片会死锁导致WK2124复位。 分析 首先ÿ…...
linux Shell编程之函数与数组(四)
目录 一. shell 函数 1. 函数的用法 (1) 两个数求和 (2) 系统资源监控并报警函数 2. 函数变量的作用范围 3. 函数的参数 4. 递归函数 二. shell 数组 (1) 获取数组长度 (2) 读取某下标赋值 (3) 数组遍历 (4) 数组切片 (5) 数组替换 (6) 数组删除 三. shell 脚本…...
4.vtk光照vtkLight
文章目录 VTK中的光照1. vtkLight 的两种类型:位置光照和方向光照2. vtkLight 的常用方法3. 方法命名风格4. vtkProp 的可见性与 vtkLight 的开关 示例 VTK中的光照 vtkLight: 用于定义一个或多个光源。每个光源可以有其颜色、位置、焦点等属性。 vtkActor: 每个vtk…...
定义AIDL 接口
目录 定义 AIDL 接口创建 .aidl 文件实现 AIDL 接口向客户端公开接口接口的版本兼容性小结1. 定义 AIDL 接口 AIDL 接口是什么? 概念 AIDL(Android 接口定义语言)用来定义跨进程通信(IPC)的接口。简单来说,它规定了客户端和服务端之间如何进行数据交换和方法调用。.aidl…...
Linux系统-scp命令--两台服务器之间传输文件
一、定义 scp是secure copy的简写,scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令,可以在linux服务器之间复制文件和目录,scp传输是加密的,可能会稍微影响一下速度。另外,scp还非常不占资源,不会提…...
Visual Studio + OpenCV C++ 安装与配置教程
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,广泛用于图像处理、视频分析、模式识别和机器学习等领域。它由Intel公司于1999年发起,并在2000年由Willow Garage(一个机器人研究机构)进一步开发和维护。OpenCV支持多种编程语言,包括C++、Python…...
怎么通过OPPO手机进行图片编辑?图片编辑攻略,打造专业级照片
在当今数字化时代,手机摄影已成为记录生活、分享瞬间的重要方式。而作为市场上广受欢迎的智能手机品牌之一,OPPO手机不仅在摄影硬件上表现出色,其内置的图片编辑功能也极为强大,能够满足使用者从基础调整到高级创作的各种需求。本…...
基于MFC 的链接库
1. 动态库 MFC Regular dll: ① DLL内部有一个CWinApp类全局对象(像是基于mfc的exe程序那样存在一个theApp),该CWinApp类的Initstance负责执行dll内部初始化。 ② DLL不能人为提供Dllmain函数,该函数由mfc库提供。 ③在visual studio 的工程配置中&a…...
2025.04.15【Connection】| 生信数据可视化:连接图绘制指南
文章目录 生信数据可视化:连接图绘制指南什么是连接地图?为什么使用连接地图?如何在R中创建连接地图?1. 安装和加载必要的库2. 准备数据3. 计算大圆航线的距离和方位角4. 创建连接地图 高级技巧1. 自定义地图样式2. 添加地理背景 …...
回溯算法:List 还是 ArrayList?一个深拷贝引发的思考
在学习和使用回溯算法解决问题时,我们经常会遇到需要维护一个结果列表,例如所有可能的子集、组合或排列。 这个结果列表通常是一个 List<List<Integer>>,其中内部的 List<Integer> 代表一个具体的解。 然而,在…...
WPS表格中设置折线图随数据列自动变化——存钱计划
效果展示: wps自动更新表格 1.公式>名称管理器>新建 2.修改名称和引用位置 OFFSET(Sheet1!$A$2,0,0,COUNTA(Sheet1!$A:$A)-1,1) 3.插入>图表 4.右键>选择数据 5.添加,输入名称和系列值。 Sheet1!名称管理器里的名字 标签分类里也填入 6如图…...
内网Windows挂载目录到公网服务器
工程目的 最近在研究图像生成,Stable Diffusion的各种模型尤其3.5以后大的飞起来,动不动五六十G,以往上传到服务器费时费力占带宽又占存储空间,更关键的是用学校服务器只能校园网才能上,上传传个半天第二天来一看发现…...
ffmpeg命令(一):信息查询命令
媒体文件信息查看 命令说明ffmpeg -i input.mp4查看媒体文件基本信息(封装格式、编解码器、时长等)ffprobe input.mp4使用专用工具查看详细信息ffprobe -v error -show_format -show_streams input.mp4输出格式和流的详细信息ffprobe -v quiet -print_f…...
2 cline 提示词工程指南-记忆库
cline 提示词工程指南-记忆库 前言 编程,就是搭建一个系统,该系统在编程过程中逐步长成,最后该系统可以完成某个具体任务。 显然,编程是一个需要仔细规划、逐步推进的系统性、流程性、逻辑性工作。 我们的 ai 能胜任么&#x…...
VueDOMPurifyHTML 防止 XSS(跨站脚本攻击) 风险
VueDOMPurifyHTML 是一个 Vue.js 插件,用于在 v-html 指令中安全地渲染 HTML 内容,防止 XSS(跨站脚本攻击) 风险。 作用 解决 v-html 的安全问题 Vue 的 v-html 会直接渲染原始 HTML࿰…...
关于SQLite轻量数据库的研究
安装本地SQLite 下载地址: https://www.sqlite.org/download.html 下载这两个包 解压到本地,得到这几个文件: 将解压后的目录添加到Path环境变量中: 在cmd中输入 “sqlite3” 和 “.open D:\work\sqliteInstall\mytestdb.…...
使用Python爬取豆瓣电影Top250并保存到Excel完整教程
在当今数据驱动的时代,获取和分析网络数据已成为许多领域的重要技能。本文将详细介绍如何使用Python爬取豆瓣电影Top250榜单数据,并将结果保存到Excel文件中。这个项目不仅适合Python初学者学习网络爬虫基础,也能帮助数据分析师获取有价值的电…...
Redis + Caffeine打造超速两级缓存架构
背景 接口的逻辑非常简单:根据传入的城市、仓库和发货时间,查询快递的预计送达时间。 然而,由于会频繁调用这个接口,尤其是在大促期间,接口的性能要求极高。 数据量虽然不大,但为了确保接口的高性能和高…...
讲讲String类的常用函数
String类在开发过程中经常用到,这里来总结一下。 1.声明与初始化 std::string str;//声明 std::string str "Hello, World!";//初始化 2.连接 std::string str1 "Hello, "; std::string str2 "World!"; std::string result …...
Sentinel实战教程:流量控制与Spring Boot集成
Sentinel实战教程:流量控制与Spring Boot集成 1. Sentinel简介与核心概念 1.1 什么是Sentinel? Sentinel是阿里巴巴开源的流量控制组件,主要用于微服务架构中的流量防护。它通过限流、熔断、热点防护等机制,帮助系统在高并发场景下保持稳定运行。 1.2 核心功能与术语 流…...
【计算机系统结构】MIPSsim
目录 双击MIPSsim.exe 问题1:Microsoft Defender SmartScreen阻止了无法是被的应用启动,运行此应用可能会导致你的电脑存在风险 解决 出现下面的问题的话,建议直接在官网下载 问题2:.NET Framework 3.5安装错误代码0x80240438 …...
Charles 安装与使用详解:实现 App 与小程序 HTTPS 抓包
在日常的移动端开发、接口调试或逆向分析中,我们经常需要抓取移动 App 或微信小程序的 HTTP/HTTPS 请求。Charles 是一款经典强大的代理抓包工具,凭借简单的界面和强大的功能,成为了 macOS 抓包的首选工具之一。 本文将详细介绍 Charles 的安…...
0415美团面试题目详解
基础知识型,基础知识!!! margin-top:100%(基于父元素宽度) “margin-top: 100% 表示元素的上外边距为父元素宽度的 100%。例如,若父元素宽 300px,则上边距为300px。需注意,CSS 中垂直方向的百分比边距(如 margin-top/margin-bottom)均基于父元素宽度计算,而非高度。这…...
【微信小程序】报错: http://127.0.0.1:7001 不在以下 request 合法域名列表中
问题 微信小程序报错: http://127.0.0.1:7001 不在以下 request 合法域名列表中,请参考文档:https://developers.weixin.qq.com/miniprogram/dev/framework/ability/network.html(env: Windows,mp,1.05.2204250; lib: 3.0.2) 解决方法: 详…...
go的json unmarshal和 k8s的deepcopy对比
Go 的 encoding/json.Unmarshal 和 Kubernetes 的 DeepCopy 虽然都依赖反射,但性能差异显著。以下是两者的对比分析及性能优化原理: 一、反射实现差异 1. json.Unmarshal 的反射特点 动态类型解析:需在运行时解析 JSON 结构,通过…...
1. k8s的简介
Kubernetes(k8s)简介 1. 产生背景 随着云计算和微服务架构的兴起,传统的单体应用逐渐被拆分为多个小型、松耦合的服务(微服务)。这种架构虽然提升了开发灵活性和可维护性,但也带来了新的挑战:…...
华为云CloudMatrix 384 超节点将有数万规模上线,赋能AI产业发展
近日,华为公司副总裁张修征表示,华为云 CloudMatrix 384 超节点今年上半年将有数万规模的上线,这或将彻底终结算力焦虑。未来,CloudMatrix 超节点可以构建超过万片的大集群来提供算力。 CloudMatrix 384超节点 华为云 CloudMatri…...
Java基础 4.15
1.重载方法练习 /* 类Methods中定义三个重载方法并调用 方法名为m 分别接受一个int参数 两个int参数 一个字符串参数 分别执行平方运算并输出 相乘并输出结果 输出字符串信息 在main()方法中分别用参数区别调用三个方法 */ public class OverLoadExercise01 {public static v…...
现代c++获取linux系统架构
现代c获取linux系统架构 前言一、使用命令获取系统架构二、使用c代码获取系统架构三、验证四、总结 前言 本文介绍一种使用c获取linux系统架构的方法。 一、使用命令获取系统架构 linux系统中可以使用arch或者uname -m命令来获取当前系统架构,如下图所示 archuna…...
shell编程之函数与数组
目录 shell函数 函数的用法 俩个数求和 系统资源监控并报警函数 函数变量的作用范围 函数的参数 递归函数 shell数组 获取数组的长度 读取某下的标赋值 数组遍历 数组切片 数组替换 数组删除 shell脚步调试 shell函数 函数的用法 Shell函数可用于存放一系列的…...
IntelliJ IDEA 中最常用的快捷键分类整理
以下是 IntelliJ IDEA 中最常用的快捷键分类整理,适用于 Windows/Linux(Mac 用户将 Ctrl 替换为 ⌘,Alt 替换为 Option): 一、编辑相关 快捷键功能说明Ctrl Space基础代码补全Ctrl Shift Space智能类型补全Ctrl P…...
大数据面试问答-Kafka/Flink
1. Kafka 1.1 定位 分布式流数据平台,核心解决三大问题: 高吞吐的实时数据管道:支持每秒百万级消息处理。 持久化的消息队列:消息持久化到磁盘,支持多订阅者。 流式数据处理:与 Flink/Spark Streaming 集…...
工厂园区光储充能量管理系统解决方案——助力高效用能与低碳运营
园区痛点:电费高、能效低、碳排压力大 安科瑞 郭海棚 198 21380729 电费成本高:峰谷电价差显著,尖峰时段用电成本激增。设备能效低:老旧设备能耗高,缺乏实时监控与优化手段。供电稳定性差:生产设备突发停电…...
Windows10下Jekyll博客部署全指南|解决GitHub模板运行失败问题
场景:在GitHub拉取的一个Jekyll博客网站运行不起来 这是想要实现的效果 这是项目代码 概要 前置要求 git版本控制工具已安装windows10环境GitHub可以正常上网 相关问题 Jekyll博客部署常见错误GitHub模板运行失败解决方法Windows10环境变量配置Ruby版本兼容性问…...
数字IC设计-VCS和Verdi的使用
#学习记录# 前言:本文以一个简单的计数器来说明vcs和verdi的使用 1 代码文件 1.1 计数器代码 //Engineer:Mr-pn-junction module counter(input clk,input rst,output reg [5:0] count); always(posedge clk or negedge rst)beginif(!rst)coun…...
FastAPI基础知识点精要
一、核心性能优势 1. 异步编程支持 原生async/await语法:支持非阻塞IO操作,轻松处理高并发场景ASGI协议实现:基于Starlette框架构建,支持WebSocket等实时协议性能基准:测试显示响应速度比Flask快3-5倍&…...
<uniapp><websocket><http>基于uniapp,手机客户端通过websocket进行数据通讯(二维码扫码数据)
前言 本专栏是基于uniapp实现手机端各种小功能的程序,并且基于各种通讯协议如http、websocekt等,实现手机端作为客户端(或者是手持机、PDA等),与服务端进行数据通讯的实例开发。 发文平台 CSDN 环境配置 系统:windows 平台:visual studio code、HBuilderX(uniapp开…...
GitLab-获取token(访问令牌)
一、操作步骤 GitLab-获取token(访问令牌)主要步骤:以及相关截图 登录 GitLab 打开 GitLab 网站并登录你的账号。 进入用户设置 点击右上角头像 → Edit profile → 左侧菜单选择 Access Tokens。 创建 Token Token name: 输入名称&#…...
python 安装win32com.client库
win32com.client是Python中用于操作Windows COM对象的强大模块,特别适合与Microsoft Office应用程序(如Word、Excel、Outlook等)进行交互。 1. 安装win32com.client 需要安装pywin32库: pip install pywin32如果安装失败或速度慢,可以使用国…...
流量统计--Maven依赖
新建项目Flow 创建依赖,在pm.xml里添加如下内容: <!-- 添加hadoop-client 3.1.3的依赖--> <dependencies> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>…...
L1-6 大勾股定理(PTA)
大勾股定理是勾股定理的推广:对任何正整数 n 存在 2n1 个连续正整数,满足前 n1 个数的平方和等于后 n 个数的平方和。例如对于 n1 有 324252;n2 有 102112122132142 等。给定 n,本题就请你找出对应的解。 输入格式: …...
HarmonyOS-ArkUI V2装饰器: @Computed装饰器:计算属性
引 @Computed是用来装饰一个自己写的getter方法的装饰器,它可以让您像用平常的状态变量那样去用这个getter方法。那么getter方法里怎么获取的值,必然涉及到您写的逻辑。这个逻辑可以是很复杂的一种计算方式,经过一系列复杂方式计算完您吐出相应的结果即可。 为了便于理解,…...
豆瓣图书数据采集与可视化分析
文章目录 一、适用题目二、豆瓣图书数据采集1. 图书分类采集2. 爬取不同分类的图书数据3. 各个分类数据整合 三、豆瓣图书数据清洗四、数据分析五、数据可视化1. 数据可视化大屏展示 源码获取看下方名片 一、适用题目 基于Python的豆瓣图书数据采集与分析基于Python的豆瓣图书…...
网络安全·工具篇1·Nmap的运用
今天我们要介绍网络安全中常用的一种扫描工具Nmap,它被设计用来快速扫描大型网络,主要功能包括主机探测、端口扫描以及版本检测,小编将在下文详细介绍Nmap相应的命令。 Nmap的下载安装地址为:Nmap: the Network Mapper - Free Se…...
MVCC详细介绍及面试题
目录 1.什么是mvcc? 2.问题引入 3. MVCC实现原理? 3.1 隐藏字段 3.2 undo log 日志 3.2.1 undo log版本链 3.3 readview 3.3.1 当前读 编辑 3.3.2 快照读 3.3.3 ReadView中4个核心字段 3.3.4 版本数据链访问的规则(了解&#x…...
designware IP如何被FPGA综合
DW的IP要被vivado等综合还是很麻烦的,而是用synplify等综合工具,然后再嫁接到vivado中也非常麻烦。本文提供一种解决办法。 1. 对DW的IP进行gtech综合。即使用DC工具对DW IP进行综合。而使用的综合库是gtech。脚本如下: set target_library…...