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

C++共享智能指针

C++中没有垃圾回收机制,必须自己释放分配的内存,否则就会造成内存泄漏。解决这个问题最有效的方式是使用智能指针。

智能指针是存储指向动态分配(堆)对象指针的类,用于生存期的控制,能够确保在离开指针所在作用域时,自动销毁动态分配的对象,防止内存泄漏。智能指针的核心实现技术是引用计数,每使用它一次,内部引用计数加1,每析构一次,内部的引用计数减1,减为0时,删除所指的堆内存。

C++提供了三种智能指针,使用前需要引用头文件<memory>:

std::shared_ptr:共享的智能指针

std::shared_ptr:独占的智能指针

std::weak_ptr:弱引用的智能指针,不共享指针,不能操作资源,是用来监视shared_ptr的

shared_ptr

计数函数

共享智能指针是指多个智能指针可以同时管理同一块有效的内存,共享智能指针shared_ptr 是一个模板类,如果要进行初始化有三种方式:通过构造函数、std::make_shared辅助函数以及reset方法。共享智能指针对象初始化完毕之后就指向了要管理的那块堆内存,如果想要查看当前有多少个智能指针同时管理着这块内存可以使用共享智能指针提供的一个成员函数use_count,函数原型如下:long use_count() const noexcept;

使用方式如下:

#include <iostream>
#include <memory>int main() {std::shared_ptr<int> sp1 = std::make_shared<int>(10);std::shared_ptr<int> sp2 = sp1;std::shared_ptr<int> sp3 = sp1;std::cout << "sp1 use_count: " << sp1.use_count() << std::endl;std::cout << "sp2 use_count: " << sp2.use_count() << std::endl;std::cout << "sp3 use_count: " << sp3.use_count() << std::endl;return 0;
}

首先创建了一个 shared_ptr 对象 sp1,并通过 make_shared 初始化它指向一个值为 10的 int对象。然后 sp2 和 sp3 都赋值为 sp1,此时这三个 shared_ptr 都指向同一个int对象。
当调用 sp1.use_count()sp2.use_count() 和 sp3.use_count() 时,都会返回 ,因为有三个shared_ptr 指向同一个对象。

初始化方式

使用构造函数初始化:std::shared_ptr<T> 智能指针名字(创建堆内存);

使用方式如下:

#include <iostream>
#include <memory>
using namespace std;int main()
{// 使用智能指针管理一块 int 型的堆内存shared_ptr<int> ptr1(new int(520));cout << "ptr1管理的内存引用计数: " << ptr1.use_count() << endl;//输出1// 使用智能指针管理一块字符数组对应的堆内存shared_ptr<char> ptr2(new char[12]);cout << "ptr2管理的内存引用计数: " << ptr2.use_count() << endl;//输出1// 创建智能指针对象, 不管理任何内存shared_ptr<int> ptr3;cout << "ptr3管理的内存引用计数: " << ptr3.use_count() << endl;//输出0// 创建智能指针对象, 初始化为空shared_ptr<int> ptr4(nullptr);cout << "ptr4管理的内存引用计数: " << ptr4.use_count() << endl;//输出0return 0;
}

如果智能指针被初始化了一块有效内存,那么这块内存的引用计数+1,如果没有被初始化或者被初始化为nullptr空指针,那么引用计数不会+1。此外,不要使用一个原始指针初始化多个shared_ptr。比如说:

int *p = new int;shared_ptr<int> p1(p);shared_ptr<int> p2(p);//error!会报错


使用拷贝和移动构造函数初始化:

#include <iostream>
#include <memory>
using namespace std;int main()
{// 使用智能指针管理一块 int 型的堆内存, 内部引用计数为 1shared_ptr<int> ptr1(new int(520));cout << "ptr1管理的内存引用计数: " << ptr1.use_count() << endl;//输出1//调用拷贝构造函数shared_ptr<int> ptr2(ptr1);cout << "ptr2管理的内存引用计数: " << ptr2.use_count() << endl;//输出2shared_ptr<int> ptr3 = ptr1;cout << "ptr3管理的内存引用计数: " << ptr3.use_count() << endl;//输出3//调用移动构造函数shared_ptr<int> ptr4(std::move(ptr1));cout << "ptr4管理的内存引用计数: " << ptr4.use_count() << endl;//输出3std::shared_ptr<int> ptr5 = std::move(ptr2);cout << "ptr5管理的内存引用计数: " << ptr5.use_count() << endl;//输出3return 0;
}

如果使用拷贝的方式初始化共享智能指针对象,这两个对象会同时管理同一块堆内存,堆内存对应的引用计数也会增加;如果使用移动的方式初始智能指针对象,只是转让了内存的所有权,管理内存的对象并不会增加,因此内存的引用计数不会变化


通过make_shared初始化:shared_ptr<T> make_shared( Args&&... args)

它可以在一次内存分配中同时完成对象的创建和 shared_ptr 的初始化,提高效率并减少内存泄漏风险。

#include <iostream>
#include <string>
#include <memory>
using namespace std;class Test
{
public:Test() {cout << "construct Test..." << endl;}Test(int x) {cout << "construct Test, x = " << x << endl;}Test(string str) {cout << "construct Test, str = " << str << endl;}~Test(){cout << "destruct Test ..." << endl;}
};int main()
{// 使用智能指针管理一块 int 型的堆内存, 内部引用计数为 1shared_ptr<int> ptr1 = make_shared<int>(520);cout << "ptr1管理的内存引用计数: " << ptr1.use_count() << endl;shared_ptr<Test> ptr2 = make_shared<Test>();cout << "ptr2管理的内存引用计数: " << ptr2.use_count() << endl;shared_ptr<Test> ptr3 = make_shared<Test>(520);cout << "ptr3管理的内存引用计数: " << ptr3.use_count() << endl;shared_ptr<Test> ptr4 = make_shared<Test>("我是要成为海贼王的男人!!!");cout << "ptr4管理的内存引用计数: " << ptr4.use_count() << endl;return 0;
}

使用std::make_shared()模板函数可以完成内存地址的创建,并将最终得到的内存地址传递给共享智能指针对象管理。如果申请的内存是普通类型,通过函数的()可完成地址的初始化,如果要创建一个类对象,函数的()内部需要指定构造对象需要的参数,也就是类构造函数的参数。


通过reset方法初始化

共享智能指针提供std::shared_ptr::reset方法函数原型如下:

ptr:指向要取得所有权的对象的指针

d:指向要取得所有权的对象的指针

aloc:内部存储所用的分配器

#include <iostream>
#include <string>
#include <memory>
using namespace std;int main()
{// 使用智能指针管理一块 int 型的堆内存, 内部引用计数为 1shared_ptr<int> ptr1 = make_shared<int>(520);shared_ptr<int> ptr2 = ptr1;shared_ptr<int> ptr3 = ptr1;shared_ptr<int> ptr4 = ptr1;cout << "ptr1管理的内存引用计数: " << ptr1.use_count() << endl;//4cout << "ptr2管理的内存引用计数: " << ptr2.use_count() << endl;//4cout << "ptr3管理的内存引用计数: " << ptr3.use_count() << endl;//4cout << "ptr4管理的内存引用计数: " << ptr4.use_count() << endl;//4ptr4.reset();cout << "ptr1管理的内存引用计数: " << ptr1.use_count() << endl;//3cout << "ptr2管理的内存引用计数: " << ptr2.use_count() << endl;//3cout << "ptr3管理的内存引用计数: " << ptr3.use_count() << endl;//3cout << "ptr4管理的内存引用计数: " << ptr4.use_count() << endl;//0shared_ptr<int> ptr5;ptr5.reset(new int(250));cout << "ptr5管理的内存引用计数: " << ptr5.use_count() << endl;//1return 0;
}

std::shared_ptr 的 reset 函数用于改变 shared_ptr 所管理的对象,它有以下几种作用:

一、释放当前管理的对象(如果有)并接管新对象

  1. 当不带参数调用 reset 函数时(如 ptr4.reset();):
    • 它会将当前 shared_ptr(这里是 ptr4)所管理的对象的引用计数减 1。如果引用计数变为 0,则释放该对象所占用的内存。在这个例子中,ptr4 原本和 ptr1ptr2ptr3 指向同一个对象(值为 520 的 int),调用 reset 后,该对象的引用计数从 4 变为 3,因为 ptr4 不再指向它。
    • 同时,ptr4 被设置为一个空的 shared_ptr,即它不再管理任何对象,其内部的指针被设置为 nullptr

二、接管新分配的对象

  1. 当带参数调用 reset 函数时(如 ptr5.reset(new int(250));):
    • 首先,它会释放 ptr5 当前可能管理的任何对象(在这个例子中,ptr5 最初是空的,所以没有对象需要释放)。
    • 然后,它会使用传入的指针(这里是通过 new int(250) 创建的新的 int 对象的指针)来初始化 ptr5,使 ptr5 管理这个新的对象。此时,新对象的引用计数被初始化为 1,因为只有 ptr5 指向它。

三、注意事项

  1. 内存管理
    • 使用 reset 函数时要小心,特别是在传递指针给 reset 时。确保传递的指针是通过 new 动态分配的内存,或者是与 shared_ptr 兼容的内存分配方式(例如,使用 std::allocate_shared 分配的内存)。如果传递了一个不适当的指针,可能会导致内存泄漏或其他未定义行为。
  2. 引用计数的变化
    • 每次调用 reset 都会影响引用计数,并且可能导致对象的释放。在多线程环境中,如果多个 shared_ptr 同时访问和修改同一个对象,需要注意对 reset 函数的调用顺序和并发访问的安全性,以避免意外的引用计数变化和对象释放。虽然 shared_ptr 的引用计数操作在一定程度上是线程安全的,但复杂的操作序列可能仍然需要额外的同步措施来确保正确性。
  3. 与其他智能指针操作的结合
    • reset 函数通常与 shared_ptr 的其他操作(如赋值、拷贝构造等)结合使用。例如,在函数返回 shared_ptr 时,可以使用 reset 来确保返回的 shared_ptr 正确管理对象的生命周期。同时,在对象的所有权转移场景中,reset 可以用于明确地释放当前的所有权并转移到新的 shared_ptr 上。但要注意在这些操作中保持逻辑的正确性,避免出现悬空指针、内存泄漏或对象被过早释放等问题。

获取原始指针

通过智能指针可以管理一个普通变量或者对象的地址,此时原始地址就不可见了。

当我们想要修改变量或者对象中的值的时候,就需要从智能指针对象中先取出数据的原始内存的地址再操作,解决方案是调用共享智能指针类提供的 get() 方法,其函数原型如下:

T* get() const noexcept;

使用如下:

#include <iostream>
#include <string>
#include <memory>
using namespace std;int main()
{int len = 128;shared_ptr<char> ptr(new char[len]);// 得到指针的原始地址char* add = ptr.get();memset(add, 0, len);strcpy(add, "我是要成为海贼王的男人!!!");cout << "string: " << add << endl;shared_ptr<int> p(new int);*p = 100;cout << *p.get() << "  " << *p << endl;return 0;
}
  • memset(add, 0, len);add指向的内存区域(即ptr管理的字符数组)的len个字节设置为0,这是一种初始化内存的操作,确保数组中的内容在复制字符串之前是清空的
  • strcpy(add, "我是要成为海贼王的男人!!!");将字符串常量复制到add指向的字符数组中。这里使用了strcpy函数,它会将源字符串的字符逐个复制到目标数组中,直到遇到字符串结束符'\0'。需要注意的是,strcpy函数在复制字符串时不会检查目标数组的大小,如果源字符串长度超过目标数组长度,会导致缓冲区溢出错误。在实际应用中,更安全的做法是使用strncpy函数,并确保正确处理字符串长度和数组大小的关系。
  • shared_ptr<int> p(new int);创建了一个shared_ptr对象p,它管理一个动态分配的int对象。
  • *p = 100;通过解引用p来访问它所管理的int对象,并将其值设置为100
  • cout << *p.get() << " " << *p << endl;分别通过p.get()获取原始指针并解引用和直接解引用p来输出int对象的值。这两种方式都可以正确获取p所管理的int对象的值,并且输出结果相同,都是100这里展示了两种访问shared_ptr所管理对象的方式,在实际使用中可以根据具体情况选择。

 指定删除器

当智能指针管理的内存对应的引用计数变为0的时候,这块内存就会被智能指针析构掉了。另外,我们在初始化智能指针的时候也可以自己指定删除动作,这个删除操作对应的函数被称之为删除器,这个删除器函数本质是一个回调函数,我们只需要进行实现,其调用是由智能指针完成的。

#include <iostream>
#include <memory>
using namespace std;// 自定义删除器函数,释放int型内存
void deleteIntPtr(int* p)
{delete p;cout << "int 型内存被释放了...";
}int main()
{shared_ptr<int> ptr(new int(250), deleteIntPtr);return 0;
}

删除器也可以是lambda表达式,因此也可以这么写:

shared_ptr<int> ptr(new int(250), [](int* p) {delete p; });

在上面的代码中,lambda表达式的参数就是智能指针管理的内存的地址,有了这个地址之后函数体内部就可以完成删除操作了。

在C++11中使用shared_ptr管理动态数组时,需要指定删除器,因为std::shared_ptr的默认删除器不支持数组对象,具体的处理代码如下:

shared_ptr<int> ptr(new int[10], [](int* p) {delete[]p; });

在删除数组内存时,除了自己编写删除器,也可以使用C++提供的std::default_delete<T>()函数作为删除器,这个函数内部的删除功能也是通过调用delete来实现的,要释放什么类型的内存就将模板类型T指定为什么类型即可。具体处理代码如下:

shared_ptr<int> ptr(new int[10], default_delete<int[]>());

另外,我们还可以自己封装一个make_shared_array方法来让shared_ptr支持数组,代码如下:

#include <iostream>
#include <memory>
using namespace std;template <typename T>
shared_ptr<T> make_share_array(size_t size)
{// 返回匿名对象return shared_ptr<T>(new T[size], default_delete<T[]>());
}int main()
{shared_ptr<int> ptr1 = make_share_array<int>(10);cout << ptr1.use_count() << endl;shared_ptr<char> ptr2 = make_share_array<char>(128);cout << ptr2.use_count() << endl;return 0;
}

相关文章:

C++共享智能指针

C中没有垃圾回收机制&#xff0c;必须自己释放分配的内存&#xff0c;否则就会造成内存泄漏。解决这个问题最有效的方式是使用智能指针。 智能指针是存储指向动态分配(堆)对象指针的类&#xff0c;用于生存期的控制&#xff0c;能够确保在离开指针所在作用域时&#xff0c;自动…...

数学建模学习(138):基于 Python 的 AdaBoost 分类模型

1. AdaBoost算法简介 AdaBoost(Adaptive Boosting)是一种经典的集成学习算法,由Yoav Freund和Robert Schapire提出。它通过迭代训练一系列的弱分类器,并将这些弱分类器组合成一个强分类器。算法的核心思想是:对于被错误分类的样本,在下一轮训练中增加其权重;对于正确分类…...

sqlite-vec一个SQLite3高效向量搜索扩展--JDBC环境使用

最近要用SQLite3&#xff0c;之前放出来了SQLiteUtile工具&#xff0c;方便操作。今天发现AIGC方面&#xff0c;RAG知识库需要使用向量数据库&#xff0c;来存储知识信息。一般呢都是用mysql&#xff0c;但无奈的是mysql就是不让用。突然又发现SQLite3有向量库扩展组件&#xf…...

Spark SQL操作

Spark SQL操作 文章目录 Spark SQL操作一、DataFrame的创建与保存1.前提操作2.数据准备3.创建4.保存DataFrame 二、DataFrame的操作1.printSchema2.show3.select4.filter5.groupBy(filed)6.sort(field) 三、临时表操作1.创建临时表2.通过临时表及SQL语句进行查询 四、从RDD转换…...

【大模型】LLaMA: Open and Efficient Foundation Language Models

链接&#xff1a;https://arxiv.org/pdf/2302.13971 论文&#xff1a;LLaMA: Open and Efficient Foundation Language Models Introduction 规模和效果 7B to 65B&#xff0c;LLaMA-13B 超过 GPT-3 (175B)Motivation 如何最好地缩放特定训练计算预算的数据集和模型大小&…...

聚焦AI存储,联想凌拓全力奔赴

【全球存储观察 &#xff5c; 科技热点关注】 每一个时代&#xff0c;都有每一个时代的骄傲。 在信息化时代&#xff0c;NAS文件存储肩负着非结构化数据管理与存储的重任&#xff0c;NetApp以其创新实力&#xff0c;赢得了全球存储市场的极高声誉。 在数智化时代&#xff0c;…...

ansible常用模块

一.ansible常用模块 ansible [主机or组列表] -m 模块 -a "参数"1.shell:类似于在终端上直接输入命令,支持bash特性2.command(默认模块):使用的变量需要事先定义好,不支持bash特性&#xff0c;如管道、重定向3.script: 执行脚本,支持python,shell脚本4.file:用于在被控…...

window11编译pycdc.exe

一、代码库和参考链接 在对python打包的exe文件进行反编译时&#xff0c;会使用到uncompyle6工具&#xff0c;但是这个工具只支持python3.8及以下&#xff0c;针对更高的版本的python则不能反编译。 关于反编译参考几个文章&#xff1a; Python3.9及以上Pyinstaller 反编译教…...

C语言——break、continue、goto

目录 一、break 二、continue 1、在while循环中 2、在for循环中 三、go to 一、break 作用是终止循环&#xff0c;在循环内遇到break直接就跳出循环。 注&#xff1a; 一个break语句只能跳出一层循环。 代码演示&#xff1a; #include<stdio.h>void test01() {for (…...

实战OpenCV之人脸识别

基础入门 随着计算机视觉技术和深度学习的发展,人脸识别已经成为一项广泛应用的技术,涵盖了从安全监控、身份验证、智能家居到大型公共安全项目等多个领域。 人脸识别技术通常包括以下几个主要步骤。 图像采集:通过摄像头或其他图像采集设备,捕获包含人脸的图像或视频帧。 …...

记录第一次安装laravel项目

window系统 Laravel中文文档&#xff1a;https://laravel-docs.catchadmin.com/docs/11/getting-started/installation 1.使用composer安装全局laravel composer global require laravel/installer2.安装完成后在命令行输入laravel&#xff0c;如果报错&#xff1a;laravel不是…...

AWTK-WEB 快速入门(1) - C 语言应用程序

先安装 AWTK Designer 用 AWTK Designer 新建一个应用程序 2.1. 新建应用程序 这里假设应用程序的名称为 AwtkApplicationC&#xff0c;后面会用到&#xff0c;如果使用其它名称&#xff0c;后面要做相应修改。 在窗口上放置一个按钮将按钮的名称改为 “close”将按钮的文本改…...

《操作系统 - 清华大学》4 -5:非连续内存分配:页表一反向页表

文章目录 1. 大地址空间的问题2. 页寄存器&#xff08; Page Registers &#xff09;方案3. 基于关联内存(associative memory )的反向页表&#xff08;inverted page table&#xff09;4. 基于哈希&#xff08;hashed&#xff09;查找的反向页表5. 小结 1. 大地址空间的问题 …...

数据可视化复习1-Matplotlib简介属性和创建子图

1.Matplotlib简介 Matplotlib是一个Python的2D绘图库&#xff0c;它可以在各种平台上以各种硬拷贝格式和交互环境生成具有出版品质的图形。通过Matplotlib&#xff0c;开发者可以仅需要几行代码&#xff0c;便可以生成绘图、直方图、功率谱、条形图、错误图、散点图等。 以下…...

98. 验证二叉搜索树【 力扣(LeetCode) 】

文章目录 零、原题链接一、题目描述二、测试用例三、解题思路四、参考代码 零、原题链接 98. 验证二叉搜索树 一、题目描述 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只包含 小于 当…...

github中banch和tag的应用

GitHub 中的 Branch 和 Tag 之间的关系 在 GitHub 和 Git 中&#xff0c;**Branch&#xff08;分支&#xff09;**和**Tag&#xff08;标签&#xff09;**都是用来管理和标记代码的概念&#xff0c;但它们在版本控制中扮演不同的角色和有不同的用途。 --- 名词解释 1. 分支…...

鸿蒙HarmonyOS开发:一次开发,多端部署(工程级)三层工程架构

文章目录 一、工程创建1、先创建出最基本的项目工程。2、新建common、features、 products 目录 二、工程结构三、依赖关系1、oh-package.json52、配置ohpm包依赖 四、引用ohpm包中的代码1、定义共享资源2、在common模块index文件中导出3、在phone模块oh-package.json5文件中引…...

无插件H5播放器EasyPlayer.js视频流媒体播放器如何开启electron硬解码Hevc(H265)

在数字化时代&#xff0c;流媒体播放器技术正经历着前所未有的变革。随着人工智能、大数据、云计算等技术的融合&#xff0c;流媒体播放器的核心技术不断演进&#xff0c;为用户提供了更加丰富和个性化的观看体验。 EasyPlayer.js H5播放器&#xff0c;是一款能够同时支持HTTP、…...

关于vue生命周期理解示例代码

在业务运作时&#xff0c;特定的逻辑代码&#xff0c;需要在特定的阶段去执行&#xff0c;所以需要理解Vue的生命周期&#xff0c;以及各个周期内的方法&#xff0c;才能明确业务代码的编写 概述&#xff1a;Vue生命周期&#xff0c;指一个vue实例从创建到销毁的过程。 分为四…...

【MySQL数据库】C#实现MySQL数据库最简单的查询和执行函数

文章目录 前言一、查询方法二、执行方法 前言 C#和MySQL数据库是常见的数据交互&#xff0c;标准的查询和执行方法如下&#xff0c;做个记录。 一、查询方法 private static int QueryTable(string tableName, DateTime today, string stepName){int result 0; // 返回数据…...

深度学习笔记之BERT(二)BERT精简变体:ALBERT

深度学习笔记之BERT——BERT精简变体:ALBERT 引言回顾&#xff1a;ResNet对于反向传播的作用BERT的配置BERT的问题/缺陷ALBERTALBERT的策略BERT VS ALBERT 引言 上一节从 Word2vec \text{Word2vec} Word2vec上下文信息的局限性角度出发&#xff0c;介绍了 BERT \text{BERT} BE…...

Easyexcel(5-自定义列宽)

相关文章链接 Easyexcel&#xff08;1-注解使用&#xff09;Easyexcel&#xff08;2-文件读取&#xff09;Easyexcel&#xff08;3-文件导出&#xff09;Easyexcel&#xff08;4-模板文件&#xff09;Easyexcel&#xff08;5-自定义列宽&#xff09; 注解 ColumnWidth Data…...

Linux 安装 Git 服务器

一、安装 Git 1. 在 CentOS/RHEL 中使用以下命令&#xff1a; sudo yum update -y # 或者 sudo dnf update -y (在较新的系统中) sudo yum install git -y验证安装&#xff1a;git --version 2. 配置 Git 用户 git config --global user.name "Your Name" git co…...

C#学习笔记——窗口停靠控件WeifenLuo.WinFormsUI.Docking使用-腾讯云开发者社区-腾讯云

C#学习笔记——窗口停靠控件WeifenLuo.WinFormsUI.Docking使用-腾讯云开发者社区-腾讯云 C#学习笔记——窗口停靠控件WeifenLuo.WinFormsUI.Docking使用 发布于 2021-06-10 00:10:59 7.1K0 举报 文章被收录于专栏&#xff1a;c#学习笔记 一、介绍 DockPanelSuite是托管在…...

c++-有关输出、信息输入、趣味输入应用、运算符、变量、浮点数数据类型的基础知识

C是一种功能强大且广泛使用的编程语言&#xff0c;它可以用于开发各种类型的应用程序。在这篇文章中&#xff0c;我们将介绍C程序的输出、信息输入、趣味输入应用、运算符、变量和浮点数数据类型的基础知识。 目录 输出 信息输入 趣味输入应用 运算符 变量 浮点数数据类…...

STM32-- keil 的option for target使用

keil版本号 1.device界面 如&#xff1a;stm32f103c8t6的工程&#xff0c;可以直接在device这里修改成stm32f103vct6&#xff0c;虽然引脚不一样&#xff0c;但是很多一样的地方&#xff0c;可以直接使用&#xff0c;有些不修改也可以下载程序。 2.target xtal的设置不起作用了…...

Python 使用 Token 认证方案连接 Kubernetes (k8s) 的详细过程

在 Kubernetes 中&#xff0c;使用 Token 认证是一种常见的客户端身份验证方式&#xff0c;尤其适用于 ServiceAccount。以下是详细的步骤&#xff0c;包括如何查看 Token、获取 API 服务地址、配置远程连接&#xff0c;以及如何在 Python 中连接 k8s。 1. 获取 Token 首先&a…...

神经网络(系统性学习二):单层神经网络(感知机)

此前篇章&#xff1a; 神经网络中常用的激活函数 神经网络&#xff08;系统性学习一&#xff09;&#xff1a;入门篇 单层神经网络&#xff08;又叫感知机&#xff09; 单层网络是最简单的全连接神经网络&#xff0c;它仅有输入层和输出层&#xff0c;没有隐藏层。即&#x…...

3D Gaussian Splatting在鱼眼相机中的应用与投影变换

paper:Fisheye-GS 1.概述 3D 高斯泼溅 (3DGS) 因其高保真度和实时渲染而备受关注。然而,由于独特的 3D 到 2D 投影计算,将 3DGS 适配到不同的相机型号(尤其是鱼眼镜头)带来了挑战。此外,基于图块的泼溅效率低下,尤其是对于鱼眼镜头的极端曲率和宽视野,这对于其更广泛…...

MATLAB的语音信号采集与处理分析

1、基本描述 本文描述的系统是一个全面而精细的语音信号处理平台&#xff0c;核心组件由MATLAB的高级功能模块构建而成。系统的核心交互界面&#xff0c;借助于MATLAB的uifigure函数搭建&#xff0c;为用户提供了一个直观且响应迅速的操作环境。通过设计的GUI按钮&#xff0c;如…...

H.265流媒体播放器EasyPlayer.js H5流媒体播放器如何验证视频播放是否走硬解

随着技术的不断进步和5G网络的推广&#xff0c;中国流媒体播放器行业市场规模以及未来发展趋势都将持续保持稳定的增长&#xff0c;并将在未来几年迎来新的发展机遇。流媒体播放器将继续作为连接内容创作者和观众的重要桥梁&#xff0c;推动数字媒体产业的创新和发展。 EasyPla…...

深度学习:ResNet每一层的输出形状

其中 /**在输出通道数为64、步幅为2的7 7卷积层后&#xff0c;接步幅为2的3 3的最大汇聚层,与GoogLeNet区别是每个卷积层后增加了批量规范层**/ b1 nn.Sequential(nn.Conv2d(1, 64, kernel_size7, stride2, padding3),nn.BatchNorm2d(64), nn.ReLU(),nn.MaxPool2d(kernel_s…...

牛客题库 21738 牛牛与数组

牛牛与数组题目链接 题目大意 牛牛喜欢这样的数组: 1:长度为n 2:每一个数都在1到k之间 3:对于任意连续的两个数A,B,A<=B 与(A % B != 0) 两个条件至少成立一个请问一共有多少满足条件的数组,对 1 e 9 + 7 1e^9+7 1e9+7 取模 输入格式 输入两个整数 n , k n,k n,…...

学会Lambda,让程序Pythonic一点

Lambda是Python里的高阶用法&#xff0c;要把代码写得Pythonic&#xff0c;就需要了解这些高阶用法&#xff0c;想说自己是一名真正的Python程序员&#xff0c;先要把代码写得Pythonic。 今天聊下Lambda的用法&#xff0c;写篇简短的用法说明。 Lambda是匿名函数的意思&#…...

旋转向量v和旋转矩阵R

旋转向量v和旋转矩阵R 旋转向量 v 和旋转矩阵 R 是三维空间中描述旋转的两种数学表示方式。两者的关系通过 Rodrigues 公式 建立。 1. 旋转向量v 2. 旋转矩阵R 3. 旋转向量v和旋转矩阵R的关系 两者通过 Rodrigues 公式 和特殊的矩阵运算互相转换&#xff1a; 4. 代码示例 1…...

CSS浮动:概念、特性与应用

CSS浮动是网页设计和开发中常见的布局技术之一&#xff0c;以下是CSS浮动相关的所有重要知识点&#xff1a; 一、浮动的定义与语法 浮动&#xff08;float&#xff09;属性可以指定一个元素应沿其容器的左侧或右侧放置&#xff0c;允许文本和内联元素环绕它。浮动属性最初只用…...

类和对象(下)

1.取地址运算符重载 1.1 const成员函数 • 将const修饰的成员函数称之为const成员函数&#xff0c;const修饰成员函数放到成员函数参数列表的后 ⾯。 • const实际修饰该成员函数隐含的this指针&#xff0c;表明在该成员函数中不能对类的任何成员进行修改。 const 修饰D…...

后端接受大写参数(亲测能用)

重要点引入包别引用错了 import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data;JsonSerialize Data public class Item {JsonProperty(value "Token")private String token…...

Android仿前端分页组件pagination

仿前端pagination Android仿前端分页组件pagination 最近Android原生有个需求就是做个分页组件&#xff0c;不用上拉加载&#xff0c;因为数据量太大用户喜欢前端的方式&#xff0c;UI主要是拼凑比较简单&#xff0c;主要补充了一些判断越界和数据不全的细节&#xff0c;记录方…...

网络安全中常用浏览器插件、拓展

引言 现在的火狐、Edge&#xff08; Chromium内核&#xff09;、Chrome等浏览器带有插件、拓展&#xff08;Plugin&#xff09;的功能。这些插件中有的可以过滤广告&#xff0c;有的提供便捷的翻译&#xff0c;有的提供JavaScript脚本支持&#xff0c;方便用户的使用也大大的增…...

Vue 使用 Cropper.js 实现图片裁剪功能

前言 图片裁剪功能无论是用户头像的裁剪&#xff0c;还是图片内容的精确调整&#xff0c;都成为了提升用户体验的关键一环。Vue.js 结合 Cropper.js 这一功能丰富的图片裁剪库&#xff0c;可以轻松实现高效、直观的图片裁剪功能。本文将详细介绍如何在 Vue.js 项目中集成并使用…...

Python 3 和 JSON 数据格式

Python 3 和 JSON 数据格式 Python 3 是一种广泛使用的编程语言,以其简洁明了的语法和强大的功能而闻名。JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于人阅读和编写,同时也易于机器解析和生成。Python 3 提供了内置的 json 模块,使得在 Python 程序…...

Halo 正式开源: 使用可穿戴设备进行开源健康追踪

在飞速发展的可穿戴技术领域&#xff0c;我们正处于一个十字路口——市场上充斥着各式时尚、功能丰富的设备&#xff0c;声称能够彻底改变我们对健康和健身的方式。 然而&#xff0c;在这些光鲜的外观和营销宣传背后&#xff0c;隐藏着一个令人担忧的现实&#xff1a;大多数这些…...

第一个autogen与docker项目

前提条件&#xff1a;在windows上安装docker 代码如下&#xff1a; import os import autogen from autogen import AssistantAgent, UserProxyAgentllm_config {"config_list": [{"model": "GLM-4-Plus","api_key": "your api…...

React第四节 组件的三大属性之state

前言 状态 state适用于类式组件中&#xff0c;而再函数式组件中需要使用 useState HOOK 模拟状态; React的组件就是一个状态机&#xff0c;通过与用户的交互&#xff0c;实现不同的状态&#xff0c;根据不同的状态展现出不一样的UI视图 并不是组件中所有的属性 都是组件的状态…...

在 CentOS 系统上直接安装 MongoDB 4.0.25

文章目录 步骤 1&#xff1a;配置 MongoDB 官方源步骤 2&#xff1a;安装 MongoDB步骤 3&#xff1a;启动 MongoDB 服务步骤 4&#xff1a;验证安装步骤 5&#xff1a;可选配置注意事项 以下是在 CentOS 系统上直接安装 MongoDB 4.0.25 的详细步骤&#xff1a; 步骤 1&#x…...

C++知识点总结(58):序列型动态规划

动态规划Ⅰ 一、基础1. 意义2. 序列 dp 解法 二、例题1. 最大子段和2. 删数最大子段和&#xff08;数据强度&#xff1a;pro max&#xff09;3. 最长上升子序列&#xff08;数据强度&#xff1a;pro max&#xff09;4. 3 或 5 的倍数序列5. 数码约数序列 一、基础 1. 意义 动…...

【系统架构设计师】真题论文: 论网络安全体系设计(包括解题思路和素材)

更多内容请见: 备考系统架构设计师-专栏介绍和目录 文章目录 真题题目(2014年 试题4)解题思路论文素材参考网络安全体系设计目标与原则网络安全体系的主要组成部分网络安全体系设计流程真题题目(2014年 试题4) 随着社会信息化的普及,计算机网络已经在各行各业得到了广泛…...

TypeScript学习笔记(三)

类型详细介绍 七、常用类型与语法 1.any any 的含义是&#xff1a;任意类型&#xff0c;一旦将变量类型限制为 any , 那就意味着放弃了对该变量的类型检查。 // 明确的表示a的类型是 any —— 【显式的any】 let a: any // 以下对a的赋值&#xff0c;均⽆警告 a 100 a 你…...

logstash 解析数组格式json数据:split, json

1&#xff0c;需求说明 原始数据格式&#xff1a; 1条 &#xff08;2*2&#xff09;》4个指标数据 [{"app":"aa","url":"www.1.com","metrics":[{"name":"cpu","value":11},{"name&quo…...