易语言做网站客户端/销售网站怎么做

易语言做网站客户端,销售网站怎么做,简要概括自建网站的优缺点,建设一个视频网站首页在笔试,面试中智能指针经常出现,如果你对智能指针的作用,原理,用法不了解,那么可以看看这篇博客讲解,此外本博客还简单模拟实现了各种指针,在本篇的最后还应对面试题对智能指针的知识点进行了拓…

        在笔试,面试中智能指针经常出现,如果你对智能指针的作用,原理,用法不了解,那么可以看看这篇博客讲解,此外本博客还简单模拟实现了各种指针,在本篇的最后还应对面试题对智能指针的知识点进行了拓展。希望能加深你对智能指针的理解。那么开始学习吧!

一.智能指针作用

        C++的智能指针主要作用是为了防止内存泄漏。在代码中我们new出来的对象都需要delete,但是当我们我们忘记或者代码出现异常导致没有delete对象,就会产生内存泄漏。长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等,出现内存泄漏会导致响应越来越慢,最终卡死。

        下面我们看看一个常见的因为异常导致内存泄漏的例子:

#include<iostream>
using namespace std;static int sa = 1;
int div_func(int a, int b)
{if (b == 0){throw invalid_argument("除0错误");}return a / b;
}
int Func1()
{int* a1 = new int{1};int* a2 = new int{sa};int n=div_func(*a1,*a2);sa--;delete a1;delete a2;return n;
}int main()
{try{while (1){int n = Func1();cout << n;}}catch (exception& e){cout << e.what() << endl;}return 0;
}

运行结果:

        main函数调用func1函数,func中new出了a1,和a2,然后调用div_func,当b=0,此时就会抛出异常,异常被mian函数捕获直接跳转,此时new出来的a1和a2就不会被delete,导致内存泄漏。这种代码的内存泄漏,还是比较难防备,此时就需要使用智能指针。

二.智能指针原理 

        我们首先介绍一下什么是RAII。

        RAII(Resource Acquisition Is Initialization)(资源获取即初始化)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。

        这种做法有两大好处:

  • 1.不需要显式地释放资源。
  • 2.对象所需的资源在其生命期内始终保持有效。

        智能指针也就是利用RAII的原理实现的,把管理一份资源的责任托管给了一个对象,通过构造函数获取资源,通过析构函数释放资源,看代码:

template<class T>
class SmartPtr {
public:SmartPtr(T* ptr = nullptr):_ptr(ptr){}~SmartPtr(){if (_ptr)delete _ptr;}
private:T* _ptr;
};

        这样我们就能通过类的生命周期来对资源进行管理和释放。对于最开始的代码我们只需要把 int* a1 = new int{1};int* a2 = new int{sa}代码写成SmartPtr<int > sp1=new{1};SmartPtr<int >sp2=new{sa},这样即使因为抛异常跳转到mian()函数也会因为生命周期的结束自动释放资源。上面的代码就是智能指针的基本原理。

三.智能指针介绍和使用 

C++常见的智能指针有三种,这里我们只做基本介绍和使用,详细特点我们后面实现再介绍。

1.std::unique_ptr

特点:独占资源所有权,不可复制(不能进行拷贝构造和赋值运算符重载)但支持移动语义,生命周期结束时自动释放资源,保证只有一个对象只有一个unique_ptr指针,避免重复析构。

class A
{
public:int a;A(int n){a = n;}~A(){std::cout << "调用析构" << std::endl;}};
int main()
{std::unique_ptr<A> ptr = std::make_unique<A>(1);//c++高版本写法。std::unique_ptr<A> ptr( new A(1));//第二种写法//std::unique_ptr<A> ptr1=ptr;//禁止了拷贝构造会报错std::unique_ptr<A> ptr2 = std::move(ptr);  // 所有权转移
}

2.std::shared_ptr

特点:共享资源所有权,通过引用计数管理生命周期,线程安全的引用计数更新。允许复制。

每复制一个shared_ptr,计数+1,析构一个计数-1,计数为零才调用析构。

class A
{
public:int a;A(int n){a = n;}~A(){std::cout << "调用析构" << std::endl;}};
int main()
{std::shared_ptr<A> ptr = std::make_shared<A>(1);std::shared_ptr<A> ptr1 = ptr;}

3.std::weak_ptr

  • 特点:弱引用,不影响 shared_ptr 的引用计数,需通过 lock() 提升为 shared_ptr 访问资源(后面详细讲解)。

四.简单模拟实现std::auto_ptr

        auto_ptr主要是在早期版本的C++使用,现在基本不会使用,特点是转移管理权,即当指针复制时,让新指针指向旧指针,再将旧指针指向空,我们主要做个了解。

namespace bit
{template<class T>class auto_ptr{public:auto_ptr(T* ptr = nullptr):_ptr(ptr){}//移交管理权auto_ptr(auto_ptr<T>& ap){_ptr = ap.get();ap._ptr = nullptr;}//释放原来的,接收管理权auto_ptr<T>& operator=(auto_ptr<T>& ap){if (this != &ap){// 释放当前对象中资源if (_ptr)delete _ptr;}_ptr=ap.get();ap.ptr=null;return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}~auto_ptr(){delete _ptr;}T* get(){return _ptr;}private:T* _ptr;};}class Date
{
public:Date(int year,int month,int day){_year = year;_month = month;_day = day;cout << "调用构造函数" << endl;}~Date(){cout << "调用析构" << endl;}int _year;int _month;int _day;
};
int main()
{bit::auto_ptr<int> ap1 = new int{ 1 };bit::auto_ptr<Date> ap2 = new Date{ 1,1,1 };cout << *ap1 << endl;cout << ap2->_year << endl;bit::auto_ptr<Date> ap3 = ap2;}

运行结果:

最后一行时的监视窗口:

        auto_ptr作为智能指针,当调用拷贝构造或赋值运算符重载,不允许多个智能指针指向同一个对象,而是将一个智能指针的资源管理权移交给另外一个智能指针,这种做法是不太好的,这意味着,赋值后的原auto_ptr对象将不再拥有指针的所有权,其内部指针会被置为NULL。这种行为可能导致一些潜在的错误,因为程序员可能期望原对象仍然拥有指针的所有权。很多公司明确要求不能使用auto_ptr。

五.简单模拟实现std::unique_ptr

        unique_ptr的实现原理:简单粗暴的防拷贝,下面简化模拟实现了一份UniquePtr来了解它的原理。

	template<class T>class unique_ptr{public:unique_ptr(T* ptr)	:_ptr(ptr){}unique_ptr (unique_ptr& up) = delete;unique_ptr<T>& operator=(unique_ptr& up) = delete;T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T* get(){return _ptr;}private:T* _ptr;};

        通过删除拷贝构造函数和赋值运算符重载来确保指向该资源的只有该智能指针。也就是说是一个资源只能有一个智能指针。

六.简单模拟实现std::shared_ptr

       上面的俩种指针之所以只能做到一个资源只能有一个智能指针,是因为没有解决多个智能指针指向一份资源从而导致重复析构的问题而shared_ptr可以解决这个问题

        shared_ptr的原理:是通过引用计数的方式来实现多个shared_ptr对象之间共享资源所有智能指针都指向同一个内存和引用计数。

        当有智能指针指向内存资源时,同时让共享的引用计数++,当智能指针析构时,只是让引用计数--,只有当引用计数为0时再调用指向资源的析构函数。此外为了多线程访问,对计数需要加锁保护。

        具体看代码:

namespace bit
{template<class T>class shared_ptr{public:shared_ptr(T* ptr = nullptr):_ptr(ptr), _pRefCount(new int(1)), _pmtx(new mutex){}shared_ptr(const shared_ptr<T>& sp):_ptr(sp._ptr), _pRefCount(sp._pRefCount), _pmtx(sp._pmtx){AddRef();}void Release(){_pmtx->lock();bool flag = false;if (--(*_pRefCount) == 0 && _ptr){cout << "delete:" << _ptr << endl;delete _ptr;delete _pRefCount;flag = true;}_pmtx->unlock();if (flag == true){delete _pmtx;}}void AddRef(){_pmtx->lock();++(*_pRefCount);_pmtx->unlock();}shared_ptr<T>& operator=(const shared_ptr<T>& sp){//if (this != &sp)if (_ptr != sp._ptr){Release();_ptr = sp._ptr;_pRefCount = sp._pRefCount;_pmtx = sp._pmtx;AddRef();}return *this;}int use_count(){return *_pRefCount;}~shared_ptr(){Release();}// 像指针一样使用T& operator*(){return *_ptr;}T* operator->(){return _ptr;}T* get() const{return _ptr;}private:T* _ptr;int* _pRefCount;mutex* _pmtx;};

         必须注意的是多线程的话,因为所有指针共享一个引用计数,对引用计数必须加锁访问,这里我们只做简单模拟。

七.weak_ptr的模拟实现

        weak_ptr有2个作用:

  • 打破循环引用:通过将类成员声明为 weak_ptr,避免 shared_ptr 的循环引用导致内存泄漏
  • 安全访问资源:通过 lock() 方法原子性地获取 shared_ptr,若对象已释放则返回空指针,避免悬垂指针

        下面我们引入第一个作用: 打破循环引用

        在shard_ptr中看似很安全,但是可能会出现循环引用的问题,下面让我们看看

class B;
class A {
public:std::shared_ptr<B> b_ptr;  // 强引用int a;~A() { std::cout << "A destroyed\n"; }
};
class B {
public:std::shared_ptr<A> a_ptr;  // 强引用int b;~B() { std::cout << "B destroyed\n"; }
};int main(){auto ptr_A = std::make_shared<A>();//c++新版本创建智能指针的新方法auto ptr_B = std::make_shared<B>();ptr_A->b_ptr = ptr_B;   //ptr_A的引用计数++;ptr_B->a_ptr = ptr_A;  //ptr_B的引用计数++  循环引用,引用计数均为2Bstd::cout << "运行完毕" << std::endl;
}  // mian结束,智能指针ptr_A,ptr_B引用计数只能减为1,对象未销毁

运行结果:

         可以看到我们并未成功调用对象A和B的析构函数,造成了内存泄漏。我们来分析一下原因。

        首先ptr_A指向A对象(假设为a),ptr_A的计数为1,ptr_B指向B对象(假设为b),ptr_B的计数也为1,然后 ptr_A->b_ptr = ptr_B; ptr_B->a_ptr = ptr_A; 此时ptr_A和ptr_B的计数增加为2.

        我们来画图理解。

        这里我们用控制块A和控制B代表指向A 和B的计数 ,当程序运行结束ptr_A,ptr_B调用析构时,计数都减少1,如下:

         此时指向A和B对象的计数都为1,无法自动调用析构,造成内存泄漏(new 出来的对象也是不会自动调用析构的)。

        我们要知道shared_ptr智能指针计数为0时才能调用指向对象的析构函数。

        为了解决上面的问题,我们创键了weak_ptr.

        weak_ptr一般和shard_ptr搭配使用,weak_ptr可以接受shard_prt类型的指针,但是不会影响计数。也就是说weak_ptr的构造和析构都不会增加和减少计数,同时weak_ptr也不会计数为0也不会调用指向对象的析构函数,只是充当指向作用

        我们使用weak_ptr对上面的代码进行修改。

class B;
class A {
public:std::weak_ptr<B> b_ptr;  // 强引用int a;~A() { std::cout << "A destroyed\n"; }
};
class B {
public:std::shared_ptr<A> a_ptr;  // 强引用int b;~B() { std::cout << "B destroyed\n"; }
};int main()
{auto ptr_A = std::make_shared<A>();auto ptr_B = std::make_shared<B>();ptr_A->b_ptr = ptr_B;ptr_B->a_ptr = ptr_A;std::cout << "运行完毕";
}

运行结果如下:

         我们将对象A的智能指针替换为weak_ptr,其他不变。再来分析析构过程

         首先ptr_A指向A对象,ptr_B指向B对象,计数都为1。ptr_A->b_ptr = ptr_B,此时A中的是weak_ptr<B>指针,不会增加ptr_B的计数,而 ptr_B->a_ptr = ptr_A,会增加ptr_A的计数(对哪个指针进行拷贝就是增加哪个指针的计数)。ptr_A计数为2,ptr_B计数为1。此时情况如图:

        当main结束时ptr_A调用自己的析构函数计数减少为1, 同时ptr_B自动调用自己的析构函数,计数减少为0。

        由于ptr_B计数为0需要调用b的析构函数调用b的析构函数释放资源后要调用成员变量a_ptr的析构函数(析构函数的顺序是先调用自己的,再调用成员变量的),此时控制块A计数为1(a_ptr是拷贝ptr_A的,俩者计数相同),减一后为0,计数为零需要调用a的析构函数,a的成员变量b_ptr计数为0,A可以直接析构,到此对象全部成功析构。图示如下:

        

        因此析构函数的调用顺序是先B后A,但是B对象是后于A对象被销毁的。 

        上面这么多就是为了论证weak_ptr的一个作用:​打破循环引用,避免内存泄漏。

        对于weak_ptr的第二个作用就好理解多了。 

  • 安全访问资源:通过 lock() 方法原子性地获取 shared_ptr,若对象已释放则返回空指针,避免悬垂指针。
std::weak_ptr<int> wp;
if (auto sp = wp.lock()) {  // 检查对象是否存在// 安全使用 sp
}

        wp.lock()是看计数是否为0,为0返回空,不为零返回一个shared_ptr(计数也会++)。

        以上这些讲讲的都是weak_ptr的作用和原理,下面我们给出weak_ptr的模拟实现。

template <typename T>
class WeakPtr {
public:// 默认构造函数(空指针)WeakPtr() : ptr_(nullptr), ref_count_(nullptr) {}// 从 SharedPtr 构造template <typename U>WeakPtr(const SharedPtr<U>& shared) : ptr_(shared.ptr), ref_count_(shared.ref_count) {}// 拷贝构造函数WeakPtr(const WeakPtr& other) : ptr_(other.ptr_), ref_count_(other.ref_count) {}shared_ptr<T> lock() const {if (*ptr<=0) return shared_ptr<T>();return shared_ptr<T>(ptr, ref_count_);}// 析构函数~WeakPtr() {}T& operator*(){return *ptr;}T* operator->(){return ptr;}T* get() const{return ptr;}private:T* ptr;                        // 指向对象的指针int* ref_count_;           // 指向控制块的指针// 允许 SharedPtr 访问私有成员template <typename U>friend class SharedPtr;
};

            要注意的这里只是简单实现,并不详细。

八.面试题拓展

        上面的讲解基本就能解决绝大多数的面试题了,但是面试的知识点也越来越细了,因此我们再根据常见的面试题进行拓展。

weak_ptr真的不计数?是否有计数方式?在哪分配的空间?

        

对于1,2小问,这里我们需要介绍一下share_ptr和weak_ptr中控制块的概念。

        控制块是智能指针实现引用计数机制的核心数据结构,包含以下信息

  1. 强引用计数(use_count)​:记录当前有多少个shared_ptr持有对象。
  2. 弱引用计数(weak_count)​:记录当前有多少个weak_ptr观察对象。
  3. 对象指针:指向实际管理的对象(可能为空,若对象已被销毁)。
  4. 自定义删除器(可选)。

     也就是说shared_ptr和weak_ptr中有2个强弱俩个计数,其中强引用计数作用就是当计数为0时调用指向对象的析构函数,但控制块仍存在,弱引用作用是当​弱引用归零时控制块本身被释放。

那么控制块的作用是什么:

1. 支持weak_ptr的安全操作

  • 感知对象状态:即使对象已被销毁(强引用归零),weak_ptr仍需通过控制块判断对象是否有效(如lock()要通过控制块判断);
  • 避免悬空控制块:若控制块随对象一起释放,weak_ptr将无法判断对象是否存在,导致未定义行为

2. 避免控制块内存泄漏

  • 生命周期分离:控制块的存活由弱引用计数决定。即使对象已销毁,只要存在weak_ptr观察,控制块就必须保留以记录弱引用信息
  • 最终释放机制:当所有weak_ptr销毁(弱引用归零),控制块才会被释放,避免内存残留

这里我们在总结一下智能指针的释放流程。

释放流程

  1. 对象销毁:当最后一个shared_ptr析构时,强引用计数归零,对象被释放。
  2. 控制块保留:若仍有weak_ptr观察(弱引用计数>0),控制块继续存在。
  3. 控制块释放:当所有weak_ptr析构(弱引用归零),控制块被销毁

 对于最后1个小问,我们还需要了解控制块的分配方式

  • new分配:直接使用new时,对象和控制块分两次分配,控制块独立存在
  • make_shared优化:通过make_shared创建shared_ptr时,对象和控制块分配在同一块连续内存中,减少内存碎片和分配次数。因此第二种方法更好一点。

因此上面面试题的答案是:

weak_ptr真的不计数?是否有计数方式,在哪分配的空间。

计数,控制块中有强弱引用计数,如果是使用make_shared初始化的函数则它所在的控制块空间是在所引用的shared_ptr中同一块的空间,若是new则控制器所分配的内存与shared_ptr本身所在的空间不在同一块内存。

  好了,智能指针就讲解到这了,感觉有帮助的话,请点点赞吧,这真的很重要。

                                

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/74656.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Three.js 快速入门教程【十八】射线拾取模型——鼠标点击屏幕选中模型或物体

系列文章目录 Three.js 快速入门教程【一】开启你的 3D Web 开发之旅 Three.js 快速入门教程【二】透视投影相机 Three.js 快速入门教程【三】渲染器 Three.js 快速入门教程【四】三维坐标系 Three.js 快速入门教程【五】动画渲染循环 Three.js 快速入门教程【六】相机控件 Or…

探索抓包利器ProxyPin,实现手机APP请求抓包,支持https请求

以下是ProxyPin的简单介绍&#xff1a; - ProxyPin是一个开源免费HTTP(S)流量捕获神器&#xff0c;支持 Windows、Mac、Android、IOS、Linux 全平台系统- 可以使用它来拦截、检查并重写HTTP(S)流量&#xff0c;支持捕获各种应用的网络请求。ProxyPin基于Flutter开发&#xff0…

深入浅出Spring-Boot-3.x.pdf

通过网盘分享的文件&#xff1a;深入浅出Spring-Boot-3.x.pdf 链接: https://pan.baidu.com/s/10ZkhmeIXphEwND9Rv4EBlg?pwduatm 提取码: uatm

springboot启动事件CommandLineRunner使用

什么是CommandRunner CommandRunner是springboot启动完成时会调用的一个runner 启动参数会传递到这个runner 我们能用来做一些初始化工作和缓存预热等工作 ApplicationRunner VS CommandRunner? 这两个Runner作用一样 只是得到的启动参数格式不一样 前者是一个Argument对象…

数据可视化TensorboardX和tensorBoard安装及使用

tensorBoard 和TensorboardX 安装及使用指南 tensorBoard 和 TensorBoardX 是用于可视化机器学习实验和模型训练过程的工具。TensorBoard 是 TensorFlow 官方提供的可视化工具&#xff0c;而 TensorBoardX 是其社区驱动的替代品&#xff0c;支持 PyTorch 等其他框架。以下是它…

26考研——树与二叉树_树与二叉树的应用(5)

408答疑 文章目录 三、树与二叉树的应用哈夫曼树和哈夫曼编码哈夫曼树的定义概念带权路径长度&#xff08;WPL&#xff09;计算示例分析 哈夫曼树的构造算法描述哈夫曼树的性质示例 哈夫曼编码Huffman树的编码规则Huffman树的构建过程前缀编码前缀编码的分析及应用 Huffman树的…

【VUE】day06 动态组件 插槽 自定义指令 ESlint

【VUE】day06 动态组件 & 插槽 & 自定义指令 1. 动态组件1.1 通过不同的按钮展示不同的组件1.1.1回顾click 1.2 keep-alive的使用1.3 keep-alive对应的生命周期函数1.3.1 keep-alive的include属性1.3.2 exclude 1.4 组件注册名称和组件声明时name的区别1.4.1 组件声明时…

nodejs-原型污染链

还是老规矩&#xff0c;边写边学&#xff0c;先分享两篇文章 深入理解 JavaScript Prototype 污染攻击 | 离别歌 《JavaScript百炼成仙》 全书知识点整理-CSDN博客 Ctfshow web入门 nodejs篇 web334-web344_web334 ctfshow-CSDN博客 334-js审计 var express require(expr…

26考研——图_图的代码实操(6)

408答疑 文章目录 五、图的代码实操图的存储邻接矩阵结构定义初始化插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点显示图 邻接表结构定义初始化图插入顶点获取顶点位置在顶点 v1 和 v2 之间插入边获取第一个邻接顶点获取下一个邻接顶点…

开源webmail邮箱客户端rainloop的分支版本SnappyMail 设置发件人允许多重身份

RainLoop已多年未更新&#xff0c;SnappyMail 是 RainLoop 的分支&#xff0c;由社区维护。SnappyMail 不仅修复了漏洞&#xff0c;还增加了更多功能和优化。对 IMAP 支持更好&#xff0c;移动端体验也比 RainLoop 更细致。 安装过程和设置跟RainLoop一样&#xff1a; 以宝塔面…

海量数据场景题--查找两个大文件的URL

查找两个大文件共同的URL 给定 a、b 两个文件&#xff0c;各存放 50 亿个 URL&#xff0c;每个 URL 各占 64B&#xff0c;找出 a、b 两个文件共同的 URL。内存限制是 4G。 操作逻辑&#xff1a; 使用哈希函数 hash(URL) % 1000​ 将每个URL映射到0-999的编号 文件A切割为a0, a1…

简单ELK框架搭建

简介 ELK 框架是一套开源的日志管理和分析工具&#xff0c;由 Elasticsearch、Logstash 和 Kibana 三个主要组件组成&#xff0c;现在新增了Filebeat组件&#xff0c;可以更高效的收集数据。 Elasticsearch&#xff1a;是一个分布式、高可扩展的开源搜索引擎&#xff0c;能快速…

网络之数据链路层

数据链路层 数据链路层目标 TCP/IP提供了一种能力, 将数据可靠的从 B 跨网络送到 C 主机, 这期间是由无数次局域网转发构成的, 比如 主机B 到 路由器F 就是一次局域网通信的问题, 而数据链路层就是研究数据是如何在局域网内部转发的. 也就是说, 应用层是进行数据的处理, 传输…

基于大数据的各品牌手机销量数据可视化分析系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 时代在飞速进步&#xff0c;每个行业都在努力发展现在先进技术&#xff0c;通过这些先进的技术来提高自己的水平和优势&#xff0c;各品牌手机销量数据可视化分析系统当然不能排除在外。基于大数据的各品牌手机销量数据可视化分析系统是在实际应用和软件工程的开发原理之…

人工智能-群晖Docker部署DB-GPT

人工智能-群晖Docker部署DB-GPT 0 环境及说明1 获取dbgpt的docker镜像2 下载向量模型3 下载配置文件4 修改配置文件5 创建dbgpt容器并运行6 访问dbgpt0 环境及说明 环境项说明DSM版本DSM 7.2.1-69057 update 3Container Manager版本24.0.2-1535当前 hub.docker.com 镜像仓库中的…

C++ --- 二叉搜索树

1 二叉搜索树的概念 ⼆叉搜索树⼜称⼆叉排序树&#xff0c;它或者是⼀棵空树&#xff0c;或者是具有以下性质的⼆叉树: 1 若它的左⼦树不为空&#xff0c;则左⼦树上所有结点的值都⼩于等于根结点的值 2 若它的右⼦树不为空&#xff0c;则右⼦树上所有结点的值都⼤于等于根结点…

跨语言语言模型预训练

摘要 最近的研究表明&#xff0c;生成式预训练在英语自然语言理解任务中表现出较高的效率。在本研究中&#xff0c;我们将这一方法扩展到多种语言&#xff0c;并展示跨语言预训练的有效性。我们提出了两种学习跨语言语言模型&#xff08;XLM&#xff09;的方法&#xff1a;一种…

AOA与TOA混合定位,MATLAB例程,自适应基站数量,三维空间下的运动轨迹,滤波使用EKF

本代码实现了一个基于 到达角(AOA) 和 到达时间(TOA) 的混合定位算法,结合 扩展卡尔曼滤波(EKF) 对三维运动目标的轨迹进行滤波优化。代码通过模拟动态目标与基站网络,展示了从信号测量、定位解算到轨迹滤波的全流程,适用于城市峡谷、室内等复杂环境下的定位研究。 文…

如何通过数据可视化提升管理效率

通过数据可视化提升管理效率的核心方法包括清晰展示关键指标、及时发现和解决问题、支持决策优化。其中&#xff0c;清晰展示关键指标尤为重要。通过数据可视化工具直观地呈现关键绩效指标&#xff08;KPI&#xff09;&#xff0c;管理者能快速、准确地理解业务现状&#xff0c…

推陈换新系列————java8新特性(编程语言的文艺复兴)

文章目录 前言一、新特性秘籍二、Lambda表达式2.1 语法2.2 函数式接口2.3 内置函数式接口2.4 方法引用和构造器引用 三、Stream API3.1 基本概念3.2 实战3.3 优势 四、新的日期时间API4.1 核心概念与设计原则4.2 核心类详解4.2.1 LocalDate&#xff08;本地日期&#xff09;4.2…