C++ 11 【可变参数模板】【lambda】

💓博主CSDN主页:麻辣韭菜💓

⏩专栏分类:C++修炼之路

🚚代码仓库:C++高阶🚚

🌹关注我🫵带你学习更多C++知识
  🔝🔝

目录

 

前言

 一、新的类功能 

1.1默认成员函数——移动构造、移动赋值

1.2强制生成默认函数的关键字default:

1.3const延长生命周期的问题

 1.4禁止生成默认函数的关键字delete:

1.5 其他新功能

缺省值

 委托构造

二、可变参数模板 

利用递归函数展开

逗号表达式展开参数包

三、Lambda 

lambda表达式

 lambda表达式语法

 1.捕捉列表

函数对象与lambda表达式 


 

前言

上篇重点讲解了右值引用,本篇的可变参数模板Lambda也是11里面非常有用的。如果学会这两个以后编程会感觉非常的爽。废话不多说直接开始!!!

 一、新的类功能 

1.1默认成员函数——移动构造、移动赋值

在C++11后,类又新增了两个默认成员函数:移动构造移动赋值

针对移动构造函数和移动赋值运算符重载有一些需要注意的点如下:
  
  • 如果你没有自己实现移动构造函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中的任 意一个。那么编译器会自动生成一个默认移动构造。默认生成的移动构造函数,对于内置类 型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动构造, 如果实现了就调用移动构造,没有实现就调用拷贝构造。

  • 如果你没有自己实现移动赋值重载函数,且没有实现析构函数 、拷贝构造、拷贝赋值重载中 的任意一个,那么编译器会自动生成一个默认移动赋值。默认生成的移动构造函数,对于内 置类型成员会执行逐成员按字节拷贝,自定义类型成员,则需要看这个成员是否实现移动赋 值,如果实现了就调用移动赋值,没有实现就调用拷贝赋值。(默认移动赋值跟上面移动构造 完全类似)
  • 如果你提供了移动构造或者移动赋值,编译器不会自动提供拷贝构造和拷贝赋值。
#include "String.h"

class Person
{
public:
	Person(const char* name = "", int age = 0)
		:_name(name)
		, _age(age)
	{}
	/*Person(const Person& p)
 
	:_name(p._name)
	,_age(p._age)
	{}*/
	/*Person& operator=(const Person& p)
	{
	if(this != &p)
	{
	_name = p._name;
	_age = p._age;
	}
	return *this;
	}*/
	/*~Person()
	{}*/

private:
	gx::string _name;
	int _age;
};
int main()
{
	Person s1;
	Person s2 = s1;
	Person s3 = move(s1);
	Person s4;
	s4 = move(s2);
	return 0;
}

如果把上面代码的拷贝构造 赋值重载、析构的任意一个代码注释取消注释就会得到下面结果

为什么我们一但自己写了默认成员函数编译器就不会自己生成移动构造、赋值? 

 如果我们实现了 析构、拷贝构造、赋值重载,就证明当前的类中涉及到了 动态内存管理,是需要自己进行 深拷贝 的,编译器无能为力,移动语义 也应该根据自己的实际场景进行设计,所以编译器就没有自动生成

 那如果有些场景就需要我们自己写拷贝构造、析构、赋值重载这些函数那怎么办?

1.2强制生成默认函数的关键字default:

Person(Person&& p) = default;
Person& operator=(Person&& p) = default;
	

C++11后STL中所有容器都增加了移动构造和移动赋值

插入系列的函数也同样增加了右值的版本。

 其他容器详情请看官网cplusplus.com 

1.3const延长生命周期的问题

插入函数之所以会延长生命周期

当您创建一个临时对象并将其作为参数传递给函数时,这个临时对象的生命周期通常只在表达式中有效。一旦表达式结束,临时对象就会被销毁。但是,如果这个临时对象被传递给一个需要更长时间使用它的函数,比如一个需要对对象进行修改的函数,那么就需要延长这个临时对象的生命周期。

在C++中,如果一个函数的参数是一个const类型,这意味着函数不会修改这个对象。但是,如果这个参数是通过引用传递的,那么即使它是const,它仍然需要在函数调用期间保持有效,以便函数可以访问它。这就是所谓的生命周期延长。

既然可以延长对象生命周期那是不是也可以像这样?下图这样返回的对象加const

从结果来看显然是不可以的。出现了野引用的问题。 所以说引用也不是安全的。

 1.4禁止生成默认函数的关键字delete:

如果能想要限制某些默认函数的生成,在C++98中,是该函数设置成private,并且只声明补丁
已,这样只要其他人想要调用就会报错。在C++11中更简单,只需在该函数声明加上=delete
可,该语法指示编译器不生成对应函数的默认版本,称=delete修饰的函数为删除函数。

 

在person类中我们在拷贝构造函数后面加 =delete 就无法再使用这个这个函数。

注意:delete这个关键字只对默认成员函数有效

那什么样的类是不希望其他人来调用的它的默认成员函数?

比如IO流

 

每个IO流对象的缓冲区都是不一样的,随意拷贝都会造成资源混乱。

1.5 其他新功能

在C++98中,类中的内置类型是不对初始化的。而在C++11中出现了缺省参数 可以给类的成员给缺省值。

缺省值

 没有缺省值我们得到_a的值是随机值。

给定缺省值 1

 委托构造

什么是委托构造? 简单来说就是一个构造函数可以复用其他构造函数

class Person
{
public:
	Person(const char* name, int age)
		:_name(name)
		, _age(age)
	{}

	
	Person(const char* name)
		:Person(name, 18) // 委托构造
	{}

private:
	gx::string _name; // 自定义类型
	int _age = 1;		   // 内置类型
};

int main()
{
	Person s1("张三");

	return 0;
}

 

这个委托构造了解一下就行了,说白了还是要调用构造函数。 

二、可变参数模板 

相比C++98的模板参数,C++11模板参数变成了不是固定的,可以接受任意个类型。和printf函数的可变参数列表是类似的。只是这里的模板参数变成了类型。

下面就是一个基本可变参数的函数模板 

// Args是一个模板参数包,args是一个函数形参参数包
// 声明一个参数包Args...args,这个参数包中可以包含0到任意个模板参数。
template <class ...Args>
void ShowList(Args... args)
{}

如果要知道参数包中个数怎么解决?

template<class ...Args>
void ShowList(Args...args)
{
	cout << sizeof...(args) << endl;
}
int main()
{
	ShowList(1, 'x');
}

 如何解析出参数包里面的值?

由于语法不支持使用args[i]这样方式获取可变参数,所以我们的用一些奇招来一一获取参数包的值。

利用递归函数展开

void ShowList()
{
	cout << endl;
}
template <class T ,class ...Args>
void ShowList(const T& val, Args ...args)
{
	cout << __FUNCTION__ << "(" << sizeof...(args) << ")" << endl;
	cout << val << endl;
	ShowList(args...); //语法规定...必须在后面
}
int main()
{
	ShowList(1, 'A', std::string("sort"));
	return 0;
}

 上面结果确实调用3次ShowList这个函数再加上无参ShowList。

能不能不用模板参数T? 我就想直接用可变模板参数包?可以 。直接再套一层。

void _ShowList()
{
	cout << endl;
}
template <class T, class ...Args>
void _ShowList(const T& val, Args... args)
{
	cout << __FUNCTION__ << "(" << sizeof...(args) << ")" << endl;

	cout << val  << endl;
	_ShowList(args...);
}
template <class ...Args>
void ShowList(Args... args)
{
	_ShowList(args...);
}

int main()
{
	ShowList(1, 'A', std::string("sort"));

	return 0;
}

逗号表达式展开参数包

template <class T>
void PrintArg(T t)
{
	cout << t << " ";
}
//展开函数
template <class ...Args>
void ShowList(Args... args)
{
	int arr[] = { (PrintArg(args), 0)... };
	cout << endl;
}
int main()
{
	ShowList(1);
	ShowList(1, 'A');
	ShowList(1, 'A', std::string("sort"));
	return 0;
}

在上篇的初始化列表 我们知道C++11在arr这个数组创建时,会初始化 列表里面的内容。实现的关键是逗号表达式。我们知道逗号表达式会按顺序执行逗号前面的表达式。 

编译器通过解析变成下面表达式

{(printarg(args), 0)...}将会展开成((printarg(arg1),0), (printarg(arg2),0), (printarg(arg3),0), etc... )

为什么要写出成 (Print(args), 0) 的形式?
这是一个逗号表达式,目的是让整个式子最终返回 0,用于初始化 arr 数组

 如果不想加0也是可以的。

 可变参数模板应用场景又是什么?线程

我们知道C语言中回调函数的传参。C的方案是用的void*   而C++11的线程库用可变参数模板对void* 这个指针进行封装。通过可变参数模板,就可以快乐的传递任何参数。剩下的事交给编译器来干。

可变参数包还可以用于优化STL容器中插入函数。

以容器list为例:

int main()
{
	list<gx::string> lt;
	gx::string s1("1111");
	lt.push_back(s1);
	lt.emplace_back(s1);
	return 0;
}

 

对于是深拷贝的类是没区别的。push_back和emplace_back二者没什么区别。

我们在来看看浅拷贝的类有没有影响

#include "Date.h"
int main()
{
	/*list<gx::string> lt;
	gx::string s1("1111");
	lt.push_back(s1);
	lt.emplace_back(s1);*/
	list<Date> lt2;
	Date d1(2024, 5, 20);
	Date d2(2024, 5, 21);
	lt2.push_back(d1);
	lt2.emplace_back(d2);

	return 0;

}

也是没有差别。

那如果是 d1\d2是右值那?

也是没区别

但是是下面这种就有区别了

emplace_back直接就是构造。这是因为可变参数包在参数传递的过程中,参数包不会展开。直到构造函数才展开。其实这里可以理解成(2023,5,28)它不是一个匿名对象,在参数包的眼里它实际是3个整型。

再比如 下面这个。

有了可变参数包。编译器直接识别为const char* 的字符串。而不是一个匿名对象。 

结论:无脑用emplace_back就行。

三、Lambda 

在C++11之前,我们如果要对数据进行排序怎么做?用std::sort。

#include <algorithm>
#include <functional>
int main()
{
	int array[] = { 4,1,8,5,3,7,0,9,2,6 };
	// 默认按照小于比较,排出来结果是升序
	std::sort(array, array + sizeof(array) / sizeof(array[0]));
	// 如果需要降序,需要改变元素的比较规则
	std::sort(array, array + sizeof(array) / sizeof(array[0]), greater<int>());
	return 0;
}

如果我们要排序的是自定义类型那就需要用到仿函数。

struct Goods
{
	string _name;  // 名字
	double _price; // 价格
	int _evaluate; // 评价
	Goods(const char* str, double price, int evaluate)
		:_name(str)
		, _price(price)
		, _evaluate(evaluate)
	{}
};
struct ComparePriceLess
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		{
			return gl._price < gr._price;
		
		}	
	}
};
struct ComparePriceGreater
{
	bool operator()(const Goods& gl, const Goods& gr)
	{
		return gl._price > gr._price;
	}
};
int main()
{
	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
   3 }, { "菠萝", 1.5, 4 } };
	sort(v.begin(), v.end(), ComparePriceLess());
	
	sort(v.begin(), v.end(), ComparePriceGreater());
}

 生活中商品太多了难道每一种商品的排序都要写相应的仿函数,是不是有点太麻烦?,假设我们不以价格来进行排序。现在要求按水果的名字排序,是不是又要重写一个仿函数?

有没有一种办法一劳永逸?在C++11推出了lambda 

lambda表达式

int main()
{
	vector<Goods> v = { { "苹果", 2.1, 5 }, { "香蕉", 3, 4 }, { "橙子", 2.2,
   3 }, { "菠萝", 1.5, 4 } };
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
		return g1._price < g2._price; });
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
		return g1._price > g2._price; });
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
		return g1._evaluate < g2._evaluate; });
	sort(v.begin(), v.end(), [](const Goods& g1, const Goods& g2) {
		return g1._evaluate > g2._evaluate; });
}

 

上述代码就是使用C++11中的lambda表达式来解决,可以看出lambda表达式实际是一个匿名函

数。

 lambda表达式语法

lambda 表达式书写格式: [capture-list] (parameters) mutable -> return-type { statement
}
1. lambda 表达式各部分说明
  • [capture-list] : 捕捉列表,该列表总是出现在lambda函数的开始位置,编译器根据[]
判断接下来的代码是否为 lambda 函数 捕捉列表能够捕捉上下文中的变量供 lambda
函数使用
  • (parameters):参数列表。与普通函数的参数列表一致,如果不需要参数传递,则可以
连同 () 一起省略
  • mutable:默认情况下,lambda函数总是一个const函数,mutable可以取消其常量
性。使用该修饰符时,参数列表不可省略 ( 即使参数为空 )
  • ->returntype:返回值类型。用追踪返回类型形式声明函数的返回值类型,没有返回
值时此部分可省略。 返回值类型明确情况下,也可省略,由编译器对返回类型进行推
  • {statement}:函数体。在该函数体内,除了可以使用其参数外,还可以使用所有捕获
到的变量。
注意:
lambda 函数定义中, 参数列表和返回值类型都是可选部分,而捕捉列表和函数体可以为
。因此 C++11 最简单的lambda函数为 []{} ; lambda 函数不能做任何事情。

我们先来一个简单的lambda语法

	[](int x, int y)->int {return x + y; };

 如果函数体的语句较多我们也是可以这样写代码的

	[](int x, int y)->int 
	{
		return x + y; 
	};

我们如果要调用这个函数对象太长了,我们可以加 auto 

	auto add1 = [](int x, int y)->int 
	{
		return x + y; 
	};
	cout << add1(1, 2) << endl;

最简单的lambda表达式

//最简单的lambda表达式 该lambda表达式没有任何意义
	[] {};

 1.捕捉列表

写一个交换函数。

​
	int x = 1, y = 0;
	auto swap1 = [](int& rx, int& ry)
	{
		int tmp = rx;
		rx = ry;
		ry = tmp;
	};
	swap1(x, y);
	cout << x << " " << y << endl;

参数列表是可以省略的

省略参数时,我们就要用捕捉列表

 

这时我们可以在参数列表后面加入关键字,mutable//异变 但是没什么用

 

 还是没有交换

上面的这种捕捉方式叫做传值捕捉,传值具有常性,不能修改 这时我们需要用到引用捕捉

这里的引用捕捉就很坑,不注意看还以为是取地址!! 

 

如果参数太多怎么办?难道要在捕捉列表中一个一个的捕捉吗?当然不用。我们直接全部引用捕捉

//全部引用捕捉
auto swap2 = [&]() 
	{
		int tmp = x;
		x = y;
		y = tmp;
	};

当然还有其他的捕捉方式

 //混合捕捉
	auto func1 = [&x, y]()
	{
		//...
	};



	 //全部传值捕捉
	auto func3 = [=]()
	{
		//...
	};

	 //全部引用捕捉,x传值捕捉
	auto func4 = [&, x]()
	{
		//...
	};

 这时我们就可以用lambad来创建线程

int main()
{
	int n1, n2;
	cin >> n1 >> n2;
	thread t1([n1]( int num)
		{
			for (int i = 0; i < n1; i++)
			{
				cout << "线程:" << num << " " << i << endl;
			}
			cout << endl;
		},1);
	thread t2([n2](int num)
		{
			for (int i = 0; i < n2; i++)
			{
				cout << "线程:" << num << " " << i << endl;
			}
			cout << endl;
		}, 2);
	t1.join();
	t2.join();

	return 0;
}

如果要m个线程分别打印n次如何操作? 这里我们可以利用vector 把每个线程放进vector这个容器中。

#include <vector>
int main()
{
	int m, n;
	cin >> m >> n;
	vector<int> arr;
	arr.push_back(m);
	arr.push_back(n);
	
	vector<thread> vthds(m);
	for (int i = 0; i < arr[0]; i++)
	{
		
		
		vthds[i] = thread([i,arr]()
			{
				for (int j = 0; j< arr[1]; j++)
				{
					cout << "线程:" << i << " " << j << endl;
				}
				cout << endl;
			});
		
	}
	for (auto& t : vthds)
	{
		t.join();
	}
	return 0;
}

 当然这个打印会错乱,那是因为没有加锁导致线程串行。关于锁的问题我们在后序线程库在详细讲解。

   lambda 能不能相互赋值?
void (*PF)();
int main()
{
     auto f1 = []{cout << "hello world" << endl; };
     auto f2 = []{cout << "hello world" << endl; };
     //f1 = f2;   // 编译失败--->提示找不到operator=()
    // 允许使用一个lambda表达式拷贝构造一个新的副本
     auto f3(f2);
     f3();
     // 可以将lambda表达式赋值给相同类型的函数指针
     PF = f2;
     PF();
     return 0;
}

总结: 

捕捉列表描述了上下文中那些数据可以被 lambda 使用 ,以及 使用的方式传值还是传引用
[var] :表示值传递方式捕捉变量 var
[=] :表示值传递方式捕获所有父作用域中的变量 ( 包括 this)
[&var] :表示引用传递捕捉变量 var
[&] :表示引用传递捕捉所有父作用域中的变量 ( 包括 this)
[this] :表示值传递方式捕捉当前的 this 指针
注意:
a. 父作用域指包含 lambda 函数的语句块
b. 语法上捕捉列表可由多个捕捉项组成,并以逗号分割
比如: [=, &a, &b] :以引用传递的方式捕捉变量 a b ,值传递方式捕捉其他所有变量
[& a, this] :值传递方式捕捉变量 a this ,引用方式捕捉其他变量
c. 捕捉列表不允许变量重复传递,否则就会导致编译错误
比如: [=, a] = 已经以值传递方式捕捉了所有变量,捕捉 a 重复

d. 在块作用域以外的 lambda 函数捕捉列表必须为空
e. 在块作用域中的 lambda函数能捕捉父作用域中局部变量。
f. lambda 表达式之间不能相互赋值 ,即使看起来类型相同

函数对象与lambda表达式 

函数对象,又称为仿函数,即可以想函数一样使用的对象,就是在类中重载了 operator() 运算符的
类对象。

 lambda的大小是多大?

要清楚这个问题我们需要通过汇编

先搞一个函数对象和lambda的代码

class Rate
{
public:
	Rate(double rate) : _rate(rate)
	{}

	double operator()(double money, int year)
	{
		return money * _rate * year;
	}

private:
	double _rate;
};
int main()
{
	
		// 函数对象
	double rate = 0.49;
	Rate r1(rate);
	r1(10000, 2);

	// lambda
	auto r2 = [=](double monty, int year)->double {return monty * rate * year; };
	r2(10000, 2);

	auto f1 = [] {cout << "hello world" << endl; };
	auto f2 = [] {cout << "hello world" << endl; };

	//f1 = f2;

	return 0;
}

 

f1 和 f2通过汇编我们发现他们两个类名不同,类名不同怎么相互赋值?

这时候我们就能回答大小为什么是1了

在C++中,sizeof运算符用来确定一个类型或对象在内存中的大小。对于一个lambda表达式,sizeof返回的是这个lambda表达式对象在内存中占用的大小。

在x86 32位架构上,指针通常是4字节大小。因此,如果你的lambda表达式没有捕获任何局部变量或外部变量(或者只捕获了通过引用捕获的变量),那么lambda表达式的大小很可能是1字节,这是因为:

  1. Lambda表达式可能被编译器优化为一个很小的函数对象,它只包含一个指向其代码的指针。
  2. 在某些编译器实现中,lambda表达式可能被优化为一个空的结构体,其中只包含一个指向其代码的指针,因此sizeof返回1,表示空结构体的大小。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

78%的中小企业担心网络攻击会导致其业务中断,中小企业如何确保网络安全?

在当今数字化时代&#xff0c;网络攻击手段层出不穷&#xff0c;网络安全事件不断增加&#xff0c;根据ConnectWise的一项调查数据显示&#xff0c;94%的中小企业至少经历过一次网络攻击&#xff0c;78%的中小企业担心网络攻击会导致其业务中断&#xff0c;企业声誉受损。由此&…

opencv-python(七)

import cv2img cv2.imread(view.jpg) cv2.imshow(view.jpg, img) img_rgb cv2.cvtColor(img, cv2.COLOR_BGR2RGB) # BGR转RGB cv2.imshow(RGB Color Space, img_rgb) img_bgr cv2.cvtColor(img_rgb, cv2.COLOR_RGB2BGR) # RGB转BGR cv2.imshow(BGR Color Space, img_bgr) c…

javaspringbootmysql小程序的竞赛管理系统71209-计算机毕业设计项目选题推荐(附源码)

摘 要 随着社会的发展,社会的方方面面都在利用信息化时代的优势。互联网的优势和普及使得各种系统的开发成为必需。 本文以实际运用为开发背景, 运用软件工程原理和开发方法,它主要是采用java语言技术和mysql数库来完成对系统的设计。整个开发过程首先对竞赛管理系统进行需求分…

【网络编程开发】11.IO模型 12.IO多路复用

11.IO模型 什么是IO: IO 是 Input/Output 的缩写&#xff0c;指的是输入和输出。在计算机当中&#xff0c;IO 操作通常指将数据从一个设备或文件中读取到计算机内存中&#xff0c;或将内存中的数据写入设备或文件中。这些设备可以包括硬盘驱动器、网卡、键盘、屏幕等。 通常用…

FiRa标准UWB MAC实现(三)——距离如何获得?

继续前期FiRa MAC相关介绍,将FiRa UWB MAC层相关细节进一步进行剖析,介绍了UWB技术中最重要的一个点,高精度的距离是怎么获得的,具体使用的测距方法都有哪些,原理又是什么。为后续FiRa UWB MAC的实现进行铺垫。 3、测距方法 3.1 SS-TWR SS-TWR为Single-Sided Two-Way Ra…

01 Linux网络设置

目录 1.1 查看及测试网络 1.1.1 查看网络配置 1. 查看网络接口地址 1. 查看活动的网络接口设备 2. 查看指定的网络接口信息 2. 查看主机名称 3. 查看路由表条目 4. 查看网络连接情况 1.1.2 测试网络连接 1. 测试网络连通性 2. 跟踪数据包的路由途径 3. 测试DNS域名解析 1.2 设…

[leetcode]将二叉搜索树转化为排序的双向链表

. - 力扣&#xff08;LeetCode&#xff09; /* // Definition for a Node. class Node { public:int val;Node* left;Node* right;Node() {}Node(int _val) {val _val;left NULL;right NULL;}Node(int _val, Node* _left, Node* _right) {val _val;left _left;right _rig…

小型气象站:现代气象监测的便携化解决方案

TH-QC12在气象监测领域&#xff0c;技术的不断创新和进步推动了监测设备的多样化和便携化。小型气象站作为这一趋势下的产物&#xff0c;以其体积小、功能全、操作简便等特点&#xff0c;受到了广泛的关注和应用。 小型气象站的技术特点 小型气象站集成了多种气象传感器&…

ChatGPT做2024高考数学题能得多少分?

文章目录 1. 前言2. AI答题2.1 第一部分试题图2.2 第二部分试题图2.3 第三部分试题图 3. 结论 1. 前言 2024年高考基本上落下帷幕&#xff08;特殊省份除外&#xff09;&#xff0c;我们关注下曾经“最喜欢”的数学用 AI 能得多少分&#xff1f;当前采用 ChatGPT-4o 模型&…

说说医院网间文件传输的进化之路

作为一家大型综合医院的信息科管理人员&#xff0c;我亲眼见证了跨网间文件交换技术的不断进步。每一个阶段都伴随着不同的挑战和惊喜&#xff0c;以下是我的一些经历和感悟&#xff0c;希望能对同行们有所帮助。 在2000年代初期&#xff0c;我们医院采用物理隔离和手动传输的方…

固态硬盘格式化后能恢复数据吗?四种数据恢复方法,赶紧收藏!

格式化的固态硬盘能恢复吗&#xff1f;硬盘是电脑里面的储存配件&#xff0c;虽然说当前种类比较多&#xff0c;但是在平常使用的过程中&#xff0c;也会遇到一些数据丢失的问题。而当前造成数据丢失的很多&#xff0c;例如&#xff1a;手动误删、清空回收站、磁盘格式化等。 …

【ppyoloe+】19届智能车完全模型组非官方基线

基于十九届智能车百度完全模型组线上赛baseline修改 调整参数最高能到0.989吧 一、环境准备 1.安装PaddleDetection In [1] # 解压PaddleDetection压缩包 %cd /home/aistudio/data/data267567 !unzip -q PaddleDetection-release-2.6.zip -d /home/aistudio /home/aistud…

工业无线通信解决方案,企业在进行智能化升级改造

某大型制造企业在进行智能化升级改造,需要将分布在各个车间的数控机床、自动化生产线、AGV小车等设备连接到云端,实现设备的远程监控、数据采集分析等功能。之前工厂内部是用工业以太网连接,存在布线难、成本高、灵活性差等问题。 在了解客户需求后,我司星创易联的工程师建议客…

等保一体机在中小型企业的应用

等保一体机比较适合中小型企业。大型企业、重点行业过等保现象确实已经十分普遍。因为国家推行等级保护制度&#xff0c;面向的重点就是那些信息系统十分关键、数据价值高的领域&#xff0c;如政府机关、金融、医疗、教育等行业。 但是有一些用户需要满足等保合规要求&#xff…

[图解]企业应用架构模式2024新译本讲解13-服务层1

1 00:00:00,150 --> 00:00:05,030 接下来我们来看服务层模式 2 00:00:06,070 --> 00:00:11,740 这也是领域逻辑类型的最后一个模式 3 00:00:13,700 --> 00:00:17,110 我们前面实际上已经见过了&#xff0c;事务脚本 4 00:00:17,240 --> 00:00:19,900 的时候&…

数据结构基础(基于c++)

数据结构基础&#xff08;基于c&#xff09; 文章目录 数据结构基础&#xff08;基于c&#xff09;前言1. 递归、迭代、时间复杂度、空间复杂度2. 数据结构 数组与链表1. 数组2. 链表3. 动态数组4. 数组与链表对比 前言 参考资料&#xff1a;Hello 算法 (hello-algo.com) 1. 递…

HTML静态网页成品作业(HTML+CSS)—— 小米商城首页网页(1个页面)

&#x1f389;不定期分享源码&#xff0c;关注不丢失哦 文章目录 一、作品介绍二、作品演示三、代码目录四、网站代码HTML部分代码 五、源码获取 一、作品介绍 &#x1f3f7;️本套采用HTMLCSS&#xff0c;未使用Javacsript代码&#xff0c;共有1个页面。 二、作品演示 三、代…

基于小波样条框架的一维时间序列信号降噪方法(MATLAB R2018A)

1952年&#xff0c;DUFFIN在研究非调和Fourier级数时引入了Hilbert空间中框架的概念&#xff0c;然而并没有引起很大的反响。1986年&#xff0c;DAUBECHIES研究发现利用框架可以将L2(R)中的函数展开成类似标准正交基的级数&#xff0c;并且用框架研究函数时所需的条件要比用标准…

企业内网安全软件分享,有什么内网安全软件

内网安全&#xff1f; 其实就是网络安全的一种。 什么是内网安全软件&#xff1f; 内网安全软件是企业保障内网安全的一种重要工具。 它主要帮助企业实现对网络设备、应用程序、用户行为等方面的监控和管理&#xff0c;以预防和应对各种网络攻击。 这类软件主要用于对内网中…