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

news2024/11/17 3:22:38

异常和智能指针

  • 一.异常
    • 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.coloradmin.cn/o/1857449.html

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

相关文章

RK3568技术笔记十八 Linux GPIO驱动程序中设备树分析

这段代码是RK3568芯片的设备树&#xff08;Device Tree&#xff09;片段&#xff0c;用于描述GPIO控制器的配置。 pinctrl: pinctrl { compatible "rockchip,rk3568-pinctrl"; // 兼容性字符串&#xff0c;指定此设备树节点适用于RK3568的引脚控制器 rockchip,grf…

汽车信息安全--HSM和TEE的区别

目录 HSM TEE TEE 和 HSM 技术特点与主要应用场景 TEE 和 HSM 相结合的方案 TEE 和 HSM 在车端的分布 HSM HSM指Hardware Security Module&#xff0c;它是一种有自己独立的CPU、密码算法硬件加速器、独立Flash等&#xff0c;用于生成、存储和管理加密密钥&#xff0c;以…

2024年商业管理与金融创新国际会议(BMFI 2024)

2024年商业管理与金融创新国际会议&#xff08;BMFI 2024&#xff09; 2024 International Conference on Business Management and Financial Innovation 【重要信息】 大会地点&#xff1a;上海 大会官网&#xff1a;http://www.icbmfi.com 投稿邮箱&#xff1a;icbmfisub-co…

高并发cn.hutool.http.HttpRequest请求优化

高并发cn.hutool.http.HttpRequest请求优化 文章目录 高并发cn.hutool.http.HttpRequest请求优化优化方向Async线程池管理Http请求处理流程Tomcat接收到请求后的处理流程Tomcat的线程分配和管理方案一方案二方案三如何启用Spring Boot Actuator 优化方向 Async线程池管理 使用…

用户态协议栈06-TCP三次握手

最近由于准备软件工程师职称考试&#xff0c;然后考完之后不小心生病了&#xff0c;都没写过DPDK的博客了。今天开始在上次架构优化的基础上增加TCP的协议栈流程。 什么是TCP 百度百科&#xff1a;TCP即传输控制协议&#xff08;Transmission Control Protocol&#xff09;是…

24 常用到的截图工具

1 语录 从此世界在我面前&#xff0c; 指向着我想去的任何地方&#xff0c; 我完全而绝对的主持着我 定义&#xff1a; 截图是将计算机屏幕上的当前显示内容保存为图片文件的行为。 概念&#xff1a; 全屏截图&#xff1a;捕捉整个屏幕的截图。区域截图&#xff1a;选择屏幕上…

【第十四课】区域经济可视化——标注

一、前言 地图上说明图面要素的名称、质量与数量特征的文字或数字&#xff0c;统称为地图 注记。只有图形符号而没有注记符号的地图&#xff0c;只能是一种令人费解的 “盲图”。 地图上的注记分为名称注记、说明注记和数字注记三种。名称注记用于说明各 种事物的专有名称&…

怎么使用RSI指标分析现货黄金行情走势?

拿到一波现货黄金行情走势&#xff0c;如何着手对其进行分析呢&#xff1f;投资者只要在网络上搜索一下&#xff0c;保管能够找到各种各样的答案&#xff0c;而本文要讨论的就是其中一种&#xff0c;我们借助RSI指标进行分析。 RSI就是相对强弱指标的简称&#xff0c;这是市场中…

车间现场管理那些事

在制造企业中&#xff0c;车间现场管理是至关重要的一环。车间现场管理包括了对生产设备、生产过程、产品质量以及员工行为的管理。有效的车间现场管理能够提高生产效率&#xff0c;降低成本&#xff0c;提高产品质量&#xff0c;并且能够保障员工的安全。那么&#xff0c;车间…

License简介和Licensecc的使用

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

Linux 运维王者从不离手的10款工具

运维工程师在日常工作中频繁运用的10款工具&#xff0c;并细致阐述每款工具的功能、适用场景以及其卓越之处。 1. Shell脚本 功能&#xff1a;主要用于自动化任务和批处理作业。 适用场景&#xff1a;频繁用于文件处理、系统管理、简单的网络管理等操作。 优势&#xff1a;灵…

原装GUVCL-T10GD韩国GENICOM光电二极管紫外线传感器原厂代理商

深圳市宏南科技有限公司是韩国GenUV公司的原厂代理商&#xff0c;所售紫外线传感器均来自于原始生产厂商直接供货&#xff0c;非第三方转售。 GUVCL-T10GD 韩国GENICOM光电二极管光传感器 / 低亮度 / 紫外线 UV-C传感器 GUVCL-T10GD 采用基于氮化铟的材料 肖特基型 光电二极管…

竞赛选题 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于python 机器视觉 的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 &#x1f9ff; 更多资…

机器学习之Kmeans丨集成学习丨决策树测试

选择题 下面属于决策树的后剪枝的是&#xff1f;【 正确答案: A】 A. 把数据集分成测试集和训练集&#xff0c;用测试集构建一个足够大的决策树&#xff0c;用测试集判断叶节点合并是否能降低误差。 B. 当树到达一定深度的时候停止生长。 C. 当前节点的样本数量小于某个阈值时&…

node.js游戏网站-计算机毕业设计源码031726

摘 要 基于网络游戏的蓬勃发展&#xff0c;游戏网站发挥着吸引玩家和提高玩家之间的互动性的重要作用&#xff0c;因而&#xff0c;建设了一个以游戏为中心的游戏官网。 该游戏提供了一个大型的玩家交流互动平台&#xff0c;包括用户管理、游戏社区、游戏信息、分类信息、游戏资…

蓝卓基于三大服务全“数”推进成渝工业互联网一体化

面向成渝地区的产业特色&#xff0c;蓝卓正不断提供多行业、多场景、多维度的解决方案&#xff0c;通过最佳实践、标杆案例&#xff0c;为企业数字化转型提供可参考的示范效应。 系统解决方案服务涵盖智能石化、汽配行业、智慧大数据等解决方案。以汽配行业为例&#xff0c;针对…

EcmaScript6全新语法特性-----EcmaScript6

{ // var会越狱,但是let会有作用域 var a 1; let b 2; } var m 1; var m 2; // var变量可以多次声明,但是let只能声明一次 let n 1; // let n 2; // var声明的变量会自动提升,这里没有就会显示undefined console.log(x); var x 10; // let变量不会变化,没有就报错 // co…

FISCO BCOS跨境应用获评工信部2024年新型数字服务优秀案例

6月18日&#xff0c;国家工信部公布2024年新型数字服务优秀案例名单&#xff0c;由前海管理局报送的“基于区块链技术打造深港跨境数据验证平台促进深港数据高效可信流动”案例入选。 随着深港合作的深入推进&#xff0c;FISCO BCOS发挥国产关键技术优势&#xff0c;持续助力深…

医院信创数字化运营平台,办公、院务、内控全面数字化,低代码拓展应用、安全可控

随着政策与技术的双重驱动&#xff0c;医院OA需求已经从传统的协同办公&#xff0c;转向信创环境下的运营、管理、服务的全程数字化、智能化。目前&#xff0c;医院信创建设全面展开&#xff0c;信创需求不断增加。 01.医院数字化信创建设政策 共同助力医院的高质量发展 医疗…

【DS Solutions】一个反欺诈产品的进化,Stripe Radar

Stripe Radar 是 Stripe 提供的一项防欺诈服务&#xff0c;它利用机器学习技术来帮助商家检测和阻止信用卡欺诈行为。这篇文章是Stripe公司关于其反欺诈解决方案Stripe Radar的构建过程的介绍。文章从Stripe的防欺诈团队工程师的角度出发&#xff0c;详细讲述了Stripe Radar的工…