[C++]24:异常和智能指针

异常和智能指针

  • 一.异常
    • 1.C/C++的错误:
      • 1.C
      • 2.C++
      • 3.三个关键字:
    • 2.使用异常:
      • 1.基本概念:
      • 2.基本代码:
        • 1.基本使用:
        • 2.多个捕获:
        • 3.任意类型异常的捕获:
        • 4.异常的重新抛出:
    • 3.异常安全:
      • 1.基本概念
      • 2.构造异常:
      • 3.析构异常:
      • 4.RAII的处理思路?
      • 5.异常规范:
        • 1.正常使用:
        • 2.不正常的使用?
    • 4.自定义的异常体系
    • 5.C++标准库的异常体系:
  • 二.智能指针
    • 1.为什么需要智能指针?
      • 1.简单代码:
      • 2.内存泄漏:
    • 2.智能指针
      • 1.简单的模拟:
      • 2.auto_ptr
        • 1.简单使用:
        • 2.模拟实现auto_ptr:
      • 3.unique_ptr
      • 4.shared_ptr
      • 5.weak_ptr

一.异常

1.C/C++的错误:

1.C

1.终止当前的程序:assert断言,exit退出,导致程序无法运行完毕直接的退出。
2.返回错误码:查找这个错误码在库中对应的是什么错误。

2.C++

1.异常是一种处理错误的方式,当一个函数发现出现了无法处理的情况就可以抛出一个异常,让函数或者函数的调用者去处理抛出的异常。

3.三个关键字:

1.throw:当出现异常的时候我们通过throw关键字去抛出一个异常。
2.catch:通过catch去捕获异常,可以在catch中去对捕获到的异常进行处理,可以存在多个catch进行捕获。
3.try:try中的代码就是有可能存在异常的代码,try后一般存在catch。

2.使用异常:

1.基本概念:

1.异常可以在任意一层函数调用链中去进行捕获。
2.抛出的异常类型必须使用捕获相同类型的catch去捕获。
3.抛出异常后会直接跳到捕获异常的地方去,中间的函数正常结束。
4.当一个异常被抛出但是到main函数都没有被捕获程序就会报错。
5.可以写任意多个捕获。
6.catch后的代码可以正常执行。
7.抛出异常后在调用链上使用最近并且捕捉类型匹配的catch。
8.抛出异常对象会生成异常对象的拷贝,捕获后异常对象会被释放。
9.catch(…)捕捉任意类型的对象。

2.基本代码:

1.基本使用:
#include<iostream>
using namespace std;void divide()
{int a = 0, b = 0;cin >> a >> b;if (b == 0)throw "除0错误";cout << a / b << endl;
}int main()
{try {divide();}catch (const char* msgerror){cout << msgerror << endl;}cout << "-----------------------------" << endl;return 0;
}

在这里插入图片描述
在这里插入图片描述

2.多个捕获:
#include<iostream>
using namespace std;void pwd()
{int a = 0;cin >> a;//偶数错误:我们不希望它是一个偶数!if (a % 2 == 0)throw 2;cout << "a: " << a << endl;
}void divide()
{int a = 0, b = 0;cin >> a >> b;if (b == 0)throw "除0错误";cout << a / b << endl;try {pwd();}catch (int x){cout << "1: " << x << endl;}}int main()
{try{divide();}catch (const char* msgerror){cout << msgerror << endl;}catch (int x){cout << "2: " << x << endl;}cout << "-----------------------------" << endl;return 0;
}

在这里插入图片描述
在这里插入图片描述

3.任意类型异常的捕获:
#include<iostream>
#include<string>
using namespace std;void pwd1()
{int a = 0;cin >> a;//偶数错误:我们不希望它是一个偶数!if (a % 2 == 0)throw 2;cout << "a: " << a << endl;
}void pwd2()
{int b = 0;cin >> b;//奇数错误:我们不希望它是一个奇数!if (b % 2 != 0)throw string("b字符是一个奇数!");cout << "b: " << b << endl;
}void divide()
{int a = 0, b = 0;cin >> a >> b;if (b == 0)throw "除0错误";cout << a / b << endl;pwd1();pwd2();
}int main()
{try{divide();}catch (const char* msgerror){cout << msgerror << endl;}catch (int x){cout << "2: " << x << endl;}catch (...){cout << "unknow errmsg" << endl;}cout << "-----------------------------" << endl;return 0;
}

//1.没有增加任意类型的异常捕获:
在这里插入图片描述
//2.增加任意类型的异常捕获:

在这里插入图片描述

4.异常的重新抛出:

1.异常的重新抛出,往往是为了解决其他的问题,不是异常本身的问题我们只是通过中间的捕获去解决其他问题之后还会把未处理的异常进行重新抛出!

#include<iostream>
#include<string>
using namespace std;void pwd1()
{int a = 0;cin >> a;//偶数错误:我们不希望它是一个偶数!if (a % 2 == 0)throw 2;cout << "a: " << a << endl;
}void divide()
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;try{pwd1();}catch (...){//2.空间释放:delete[] pa;cout << "delete[] pa " << endl;//3.异常的重新抛出:throw;}
}int main()
{try{divide();}catch (const char* msgerror){cout << msgerror << endl;}catch (int x){cout << "2: " << x << endl;}cout << "-----------------------------" << endl;return 0;
}

在这里插入图片描述

在这里插入图片描述

3.异常安全:

1.基本概念

1.异常会导致执行流的乱跳,产生异常安全的问题。
2.在构造函数的时候不要去抛出异常,导致对象不完整。
3.在析构函数的时候不要去抛出异常,导致内存泄漏,空间没有完全释放。

2.构造异常:

1.问题?
2.这个对象没有开辟完整,并且pa指针没有被释放,导致内存泄漏。

#include<iostream>
#include<string>
using namespace std;void divide()
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}class A {
public:A(int n){pa = new int(n);divide();pb = new int(n);}~A(){delete[] pa;delete[] pb;cout <<"delete[] pa" << "delete[] pb" << endl;}
private:int* pa;int* pb;
};int main()
{try{A a(10);}catch (const char* msgerror){cout << msgerror << endl;}cout << "-----------------------------" << endl;return 0;
}

在这里插入图片描述
在这里插入图片描述

3.析构异常:

1.问题?
2.对象空间开辟完整,但是pb没有被正常释放导致内存泄漏。

#include<iostream>
#include<string>
using namespace std;void divide()
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}class A {
public:A(int n){pa = new int(n);pb = new int(n);}~A(){delete[] pa;divide();delete[] pb;cout <<"delete[] pa" << "delete[] pb" << endl;}
private:int* pa;int* pb;
};int main()
{try{A a(10);}catch (const char* msgerror){cout << msgerror << endl;}cout << "-----------------------------" << endl;return 0;
}

在这里插入图片描述

在这里插入图片描述

4.RAII的处理思路?

C++中的异常经常会导致资源泄漏的问题,在new和delete中抛出了异常可能导致资源泄漏,lock和unlock中导致死锁的问题,C++经常通过RAII来解决问题。RAII在下面的智能指针中去说。

5.异常规范:

1.异常规范的目的是让函数的使用者知道函数可能会抛什么类型的异常。
2.函数后面写throw()表示函数不抛异常。
3.函数后面没有写如何东西表示函数可能会抛任意类型的异常。
4.C++11中新增noexcept在函数后增加表示函数不会抛异常。

1.正常使用:
#include<iostream>
#include<string>
using namespace std;void divide() throw(const char*, int ,string)
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}int main()
{try{divide();}catch (const char* msgerror){cout << msgerror << endl;}catch (int msgerror){cout << msgerror << endl;}catch (string msgerror){cout << msgerror << endl;}cout << "-----------------------------" << endl;return 0;
}
2.不正常的使用?

//1.假设抛A,B类型的异常但是抛了C类型的异常

#include<iostream>
#include<string>
using namespace std;void divide() throw(int, string)
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}int main()
{try{divide();}catch (int msgerror){cout << msgerror << endl;}catch (string msgerror){cout << msgerror << endl;}cout << "-----------------------------" << endl;return 0;
}

//2.假设不抛异常,但是还是抛异常了?

#include<iostream>
#include<string>
using namespace std;void divide() throw()
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}int main()
{try{divide();}catch (const char* msgerror){cout << msgerror << endl;}cout << "-----------------------------" << endl;return 0;
}

在这里插入图片描述

//1.C++11新增noexcept有一定的作用!

#include<iostream>
#include<string>
using namespace std;void divide() noexcept
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}int main()
{try{divide();}catch (const char* msgerror){cout << msgerror << endl;}cout << "-----------------------------" << endl;return 0;
}

在这里插入图片描述

4.自定义的异常体系

1.如何统一的去管理异常的抛出类型呢?
2.抛出派生类的异常可以使用基类去捕获。

#include<iostream>
#include<windows.h>
#include<string>
using namespace std;void divide() noexcept
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}class except {
public:except(int id, const char* error):_id(id),_msgerror(error){}virtual string what(){return _msgerror;}~except(){}
private:int _id;const char* _msgerror;
};class sqlerro : public except {
public:sqlerro(int id, const char* error, const char* sqlerr):except(id, error), _sqlerr(sqlerr){}virtual string what(){string str = "sql message";return str;}
private:const char* _sqlerr;
};class Tcperro : public except {
public:Tcperro(int id, const char* error, const char* Tcperr):except(id, error), _Tcperr(Tcperr){}virtual string what(){string str = "TCP message";return str;}
private:const char* _Tcperr;
};void operator_sql(int& n)
{if (n % 2 == 0)throw sqlerro(2, "sql erro", "select * from user");cout << "sql success" << endl;
}void operator_Tcp(int& n)
{if (n % 3 == 0)throw Tcperro(2, "Tcp erro", "sock error");cout << "Tcp success" << endl;
}int main()
{srand(time(NULL));while (1){Sleep(1000);try{int n = rand() % 100;//1.操作库:operator_sql(n);//2.操作网络:operator_Tcp(n);}catch (except msgerror){cout << msgerror.what() << endl;}}cout << "-----------------------------" << endl;return 0;
}

在这里插入图片描述

5.C++标准库的异常体系:

在这里插入图片描述

二.智能指针

1.为什么需要智能指针?

1.简单代码:

1.我们知道new函数本身就有可能抛异常,当空间出现问题的时候。
2.连续的空间开辟需要像下面的代码一样进行异常的处理才不会出现问题。
3.有没有什么好的方法去管理呢?

#include<iostream>
#include<string>
using namespace std;void divide()
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}class A {
public:A(int n){try{pa = new int(n);try {pb = new int(n);try{pc = new int(n);}catch (...){delete[] pa;delete[] pb;}}catch (...){delete[] pa;}}}~A(){delete[] pa;delete[] pb;delete[] pc;cout << "delete[] pa" << "delete[] pb" << endl;}
private:int* pa;int* pb;int* pc;
};int main()
{try{A a(10);}catch (...){cout << "new error" << endl;}cout << "-----------------------------" << endl;return 0;
}

2.内存泄漏:

C/C++程序中一般我们关心两种方面的内存泄漏:
堆内存泄漏(Heap leak)
堆内存指的是程序执行中依据须要分配通过malloc / calloc / realloc / new等从堆中分配的一
块内存,用完后必须通过调用相应的 free或者delete 删掉。假设程序的设计错误导致这部分
内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak。
系统资源泄漏
指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放
掉,导致系统资源的浪费,严重可导致系统效能减少,系统执行不稳定。

2.智能指针

1.简单的模拟:

RAII的原理:
RAII(Resource Acquisition Is Initialization)是一种利用对象生命周期来控制程序资源(如内存、文件句柄、网络连接、互斥量等等)的简单技术。
在对象构造时获取资源,接着控制对资源的访问使之在对象的生命周期内始终保持有效,最后在对象析构的时候释放资源。借此,我们实际上把管理一份资源的责任托管给了一个对象。这种做法有两大好处:
1.不需要显式地释放资源。
2.采用这种方式,对象所需的资源在其生命期内始终保持有效

#include<iostream>
#include<string>
using namespace std;void divide()
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}template<class T>
class smart_ptr {
public:smart_ptr(T* a):_ptr(a){}~smart_ptr(){if (_ptr)delete _ptr;}
private:T* _ptr;
};class A {
public:A(int n){pa = new int(n);pb = new int(n);}~A(){delete[] pa;delete[] pb;cout << "delete[] pa" << "delete[] pb" << endl;}
private:int* pa;int* pb;
};int main()
{try{smart_ptr<A> pa = new A(10);divide();}catch (...){cout << "new error" << endl;}cout << "-----------------------------" << endl;return 0;
}

2.auto_ptr

1.简单使用:
#include<iostream>
#include<memory>
#include<string>
using namespace std;void divide()
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}void text()
{auto_ptr<int> pa(new int(10));auto_ptr<int> pb(new int(10));divide();
}int main()
{try{text();}catch (...){cout << "new error" << endl;}cout << "-----------------------------" << endl;return 0;
}
2.模拟实现auto_ptr:

auto_ptr的实现原理:管理权转移的思想,模拟实现了一份bit::auto_ptr来了解它的原理

using namespace std;
namespace sfpy {template<class T>class auto_ptr {public://1.构造:auto_ptr(T* ptr):_ptr(ptr){}//2.拷贝构造:auto_ptr(auto_ptr<T>& sp):_ptr(sp._ptr){//管理权限转移?sp._ptr = nullptr;}//3.赋值:auto_ptr<T>& operator=(auto_ptr<T>& ap){//检查自己给自己赋值的情况:if (this != &ap){//1.释放自己:if (_ptr)delete _ptr;//2.管理权限转移?_ptr = ap._ptr;ap._ptr = nullptr;}return *this;}//像指针一样:T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//析构:~auto_ptr(){if (_ptr){delete _ptr;cout << "delete _ptr" << endl;}}private:T* _ptr;};
}

3.unique_ptr

简单粗暴的防止拷贝防止赋值:
auto_ptr非常容易的产生了多次析构的问题!

在这里插入图片描述

using namespace std;
namespace sfpy {template<class T>class unique_ptr {public://1.构造:unique_ptr(T* ptr):_ptr(ptr){}//2.拷贝构造:unique_ptr(auto_ptr<T>& sp) = delete//3.赋值:unique_ptr<T>& operator=(unique_ptr<T>& ap) = delete//像指针一样:T& operator*(){return *_ptr;}T* operator->(){return _ptr;}//析构:~unique_ptr(){if (_ptr){delete _ptr;cout << "delete _ptr" << endl;}}private:T* _ptr;};
}

4.shared_ptr

shared_ptr的原理:是通过引用计数的方式来实现多个shared_ptr对象之间共享资源.

  1. shared_ptr在其内部,给每个资源都维护了着一份计数,用来记录该份资源被几个对象共享。
  2. 在对象被销毁时(也就是析构函数调用),就说明自己不使用该资源了,对象的引用计数减1。
  3. 如果引用计数是0,就说明自己是最后一个使用该资源的对象,必须释放该资源;
  4. 如果不是0,就说明除了自己还有其他对象在使用该份资源,不能释放该资源,否则其他对象就成野指针了。
#include<iostream>
#include<memory>
#include<string>
#include"shared_ptr.h"using namespace std;void divide()
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}void text()
{int* a = new int(10);sfpy::shared_ptr<int> pa(a);sfpy::shared_ptr<int> pb(pa);pb = pa;divide();
}int main()
{try{text();}catch (...){cout << "new error" << endl;}cout << "-----------------------------" << endl;return 0;
}
#pragma once#include<iostream>using namespace std;
namespace sfpy {template<class T>class shared_ptr {public://1.构造:shared_ptr(T* ptr):_ptr(ptr),_pcount(new int(1)){}//2.拷贝构造:shared_ptr(shared_ptr<T>& sp):_ptr(sp._ptr),_pcount(sp._pcount){(*_pcount)++;}//3.赋值:shared_ptr<T>& operator=(shared_ptr<T>& ap){//检查自己给自己赋值的情况:if (this != &ap){//1.原来的要减少:realse();//2.新的增加:_ptr = ap._ptr;_pcount = ap._pcount;(*_pcount)++;}return *this;}//像指针一样:T& operator*(){return *_ptr;}T* operator->(){return _ptr;}void realse(){if (_ptr && *_pcount == 1){delete _ptr;delete _pcount;cout << "delete _ptr" << "delete _pcount;" << endl;}else{(*_pcount)--;}}//析构:~shared_ptr(){realse();}private:T* _ptr;int* _pcount;};
}

在这里插入图片描述

5.weak_ptr

在这里插入图片描述

在这里插入图片描述

1.产生上面问题的本质是ListNode使用了sharedptr导致引用计数不会减到0
2.所以两个节点都不能正常的释放。
3.把ListNode节点的智能指针改变为weak_ptr

#include<iostream>
#include"shared_ptr.h"namespace sfpy {template<class T>class weak_ptr{public:weak_ptr():_ptr(nullptr){}weak_ptr(const sfpy::shared_ptr<T>& sp):_ptr(sp.get()){}weak_ptr<T>& operator=(const sfpy::shared_ptr<T>& sp){_ptr = sp.get();return *this;}T& operator*(){return *_ptr;}T* operator->(){return _ptr;}private:T* _ptr;};
}
#include<iostream>
#include<memory>
#include<string>
#include"weak_ptr.h"
#include"shared_ptr.h"using namespace std;struct ListNode {ListNode(int x):_prev(nullptr),_next(nullptr),_date(x){}sfpy::weak_ptr<ListNode> _prev;sfpy::weak_ptr<ListNode> _next;int _date;
};//struct ListNode {
//	ListNode(int x)
//		:_prev(nullptr)
//		, _next(nullptr)
//		, _date(x)
//	{}
//
//	sfpy::shared_ptr<ListNode> _prev;
//	sfpy::shared_ptr<ListNode> _next;
//	int _date;
//};void divide()
{int a = 0, b = 0;cin >> a >> b;//1.开辟空间:int* pa = new int(10);if (b == 0)throw "除0错误";cout << a / b << endl;
}void text()
{sfpy::shared_ptr<ListNode> pa(new ListNode(1));sfpy::shared_ptr<ListNode> pb(new ListNode(2));pa->_next = pb;pb->_prev = pa;divide();
}int main()
{try{text();}catch (...){cout << "new error" << endl;}cout << "-----------------------------" << endl;return 0;
}

在这里插入图片描述

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

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

相关文章

微软将停用 App Center:React Native 开发人员应该使用以下工具

再见,应用中心!你好,EAS + Sentry + GitHub Actions! React Native 开发人员大遗憾:微软宣布将于 2025 年 3 月 31 日关闭Visual Studio App Center。 多年来, Infinite Red一直将 App Center 作为许多 React Native 咨询客户的 CI/CD 流程和开发工作流程的关键部分。它有…

License简介和Licensecc的使用

License简介和Licensecc的使用 License简介什么是LIcense简易License制作加密扫盲对称加密非对称加密 Licensecc使用构建和编译在linux上进行编译UbuntuCentOS 7CentOS 8下载并编译配置编译和测试cmake 后可以跟的参数在Linux上为Windows进行交叉编译 在windos上进行编译MSVC (…

项目管理软件如何帮助收尾项目?

项目规划、执行、监测和控制通常是项目管理的重点。即使是项目启动也会受到关注&#xff0c;但项目收尾通常是事后才提及的。 实际上&#xff0c;项目的每个阶段都很重要。项目收尾不仅仅是按时交付、不超预算和达到预期质量。 什么是项目收尾&#xff1f; 项目收尾是项目生…

elementUI的衍生组件,avue的crud表格错位问题

问题描述&#xff1a; 每次从别的页面跳转回来就发现表格显示错位了 一通查 结果发现是有两层表格 解决办法&#xff1a; 根据开发者工具中看到的样式选择器&#xff0c;很粗暴的在全局样式文件中加一个&#xff1a; 效果&#xff1a;

学习记录696@网络安全之认证、报文完整性、密钥分发与证书

认证 即通信双方如何认证对方身份。 这种情况存在问题&#xff1a;trudy可以伪造A的IP地址。就算带上密码也可能被截获&#xff0c;用于重放攻击。 解决重放攻击的办法是随机数挑战&#xff0c;每次认证时&#xff0c;B都发一个挑战码给A。A加密后再传给B&#xff0c;如果B…

恒远世达:把握现在,高考后逆袭,开启日本留学之路!

一年一度的高考已经落幕&#xff0c;马上就要出高考分数了&#xff0c;有人欢喜有人忧&#xff0c;奋斗学习了这么多年&#xff0c;就为了考上一所理想的大学&#xff0c;一旦没考上&#xff0c;心情会非常的低落。 在传统心态中&#xff0c;高考失利意味着人生重大失败&#…

基于自主发明专利的杰林码哈希算法、对称加密算法和无损压缩算法的可文件追踪管控且支持linux和windows的文件压缩包工具SDK和JLM PACK软件介绍

基于自主发明专利的杰林码哈希算法、对称加密算法和无损压缩算法的可文件追踪管控且支持linux和windows的文件压缩包工具SDK1.0版发布&#xff0c;下载链接为&#xff1a; JLM PACK CSDN下载链接 JLM PACK SDK和软件的官方网站 注意测试授权证书yesine_jlmpack_test.license…

一种改进解卷积算法在旋转机械故障诊断中的应用(MATLAB)

轴承振动是随机振动。在不同的时刻&#xff0c;轴承振动值是不尽相同的&#xff0c;不能用一个确定的时间函数来描述。这是由于滚动体除了有绕轴承公转运动以外&#xff0c;还有绕自身轴线的自旋运动&#xff0c;且在轴承运转时&#xff0c;滚动接触表面形貌是不断变化的&#…

计算机中丢失vcruntime140_1.dll如何修复?分享7种常用解决方法

vcruntime140_1.dll缺失原因分析 软件卸载或更新不当在软件卸载或更新过程中&#xff0c;如果未能正确处理依赖关系&#xff0c;可能会导致vcruntime140_1.dll文件被错误地删除或损坏。 据统计&#xff0c;约有30%的DLL文件丢失问题是由于不当的卸载或更新操作引起的。 用户…

git 拉下来的项目,出现“加载失败”的解决方法

现象&#xff1a; 1、对加载失败的项目&#xff0c;尝试重新加载 解决思路&#xff1a;根据上面的提示&#xff0c;打开F盘对应的 .vcxproj文件&#xff0c;查看里面关于opencv454.props的内容 先删了&#xff0c;后面再补 2、当前的工作重点是消除加载失败的情况&#xff0c;…

Day13—大语言模型

定义 大语言模型&#xff08;Large Language Models&#xff09;是一种基于深度学习的自然语言处理&#xff08;NLP&#xff09;模型&#xff0c;用于处理和生成人类语言文本。 一、认识NLP 什么是NLP ​ NLP&#xff08;Natural Language Processing&#xff09;&#xff0…

鸿蒙NEXT实战开发: 依据前端对http请求进行二次简单封装

一、为什么要对http请求进行封装&#xff1f; 在我看来二次封装有一下几点好处 代码封装之后&#xff0c;开发人员只用关注业务层面的东西&#xff0c;不用去过多浪费时间在接口请求数据处理上。封装之后代码更加简洁&#xff0c;通俗易懂&#xff0c;方便后期维护&#xff0…

MUR4060PT-ASEMI逆变焊机MUR4060PT

编辑&#xff1a;ll MUR4060PT-ASEMI逆变焊机MUR4060PT 型号&#xff1a;MUR4060PT 品牌&#xff1a;ASEMI 封装&#xff1a;TO-247 恢复时间&#xff1a;35ns 最大平均正向电流&#xff08;IF&#xff09;&#xff1a;40A 最大循环峰值反向电压&#xff08;VRRM&#x…

Nature重磅:揭开睡眠不足为什么会损害记忆力

我们的记忆力会在睡眠期间得到增强&#xff0c;海马体是大脑的记忆中心&#xff0c;而海马体尖波涟漪&#xff08;sharp-wave ripple&#xff0c;SWR&#xff09;期间觉醒体验的激活和重放被认为是记忆力得到增强的关键。睡眠不足会损害记忆力&#xff0c;然而&#xff0c;我们…

计算机组成原理笔记-第4章 存储器

第4章 存储器 笔记PDF版本已上传至Github个人仓库&#xff1a;CourseNotes&#xff0c;欢迎fork和star&#xff0c;拥抱开源&#xff0c;一起完善。 该笔记是最初是没打算发网上的&#xff0c;所以很多地方都为了自我阅读方便&#xff0c;我理解了的地方就少有解释&#xff1b…

Tomcat简介与安装

目录 一、Tomcat 简介 1、Tomcat好帮手---JDK 2、安装Tomcat & JDK 1、系统环境说明 2 、安装JDK 3、安装Tomcat 二、Tomcat目录介绍 1、tomcat主目录介绍 2、webapps目录介绍 3、Tomcat配置介绍&#xff08;conf&#xff09; 4、Tomcat的管理 5、tomcat 配置管…

24.6.16

星期一&#xff1a; 补cf global round26 C2 cf传送门 思路&#xff1a;有效操作2只有一次&#xff0c;且反转后不会再出现负数&#xff0c;即后面能贡献 2^n-i个方案&#xff0c;再乘上前面 2^(k>0的次数) 代码如下&…

GWB—200JA型引伸计标定器

GWB一200JA型引伸计标定器&#xff0c;是一种纯机械式的高精度位移测微仪器。依据JJG762—2007引伸计检定规程要求&#xff0c;专门用于对各类引伸计的标定&#xff0c;也广泛用于位移传感器的检定及相应百分表、千分表的标定。 l、本仪器由精密微分测头及测量支架组成。该标定…

vue2+webpack 和 vite+vue3 配置获取环境变量(补充)

相关涉及知识点可看小编该文章&#xff1a; nginx: 部署前端项目的详细步骤&#xff08;vue项目build打包nginx部署&#xff09;_前端工程打包部署到nginx-CSDN博客 1.vue2webpack 我们通常会在项目中看到这么两个文件(没有则自己创建&#xff0c;文件名&#xff1a;.env.***) …

C#回车按下时 如果当前焦点的下个控件为Button 则按Button。 如果不是Button则焦点移到下个控件上

需求 扫SN 扫IMEI 扫其它 就自动点打印 帮我写这个C# 函数 “ private void FormF360ColorBox_KeyDown(object sender, KeyEventArgs e)” 回车按下时 如果当前焦点的下个控件为Button 则按Button。 如果不是Button则焦点移到下个控件上。 控件的Index 顺序要设对哦。 你可以…