与C++内存管理和STL简介的爱恨情仇

news2024/11/25 4:38:13

在这里插入图片描述

本文

    • 1.C/C++内存分布
    • 2.C语言中动态内存管理方式:malloc/calloc/realloc/free
      • 总结
    • 3.C++内存管理方式
      • new/delete操作内置类型
      • new和delete操作自定义类型
    • 4.operator new与operator delete函数(重要点进行讲解)
    • 5.new和delete的实现原理
      • 内置类型
      • 自定义类型
    • 6.定位new表达式(placement-new) (了解)
    • 7.malloc/free和new/delete的区别
    • 8.泛型编程
    • 9.函数模版
      • 模版概念
      • 函数模版格式
      • 模版的原理
      • 函数模板的实例化
      • 隐式实例化
      • 显示实例化
      • 模版参数的匹配规则
    • 10.类模版
    • 11.什么是STL
    • 12.STL的版本
    • 13.STL的六大组件
    • 14.STL的重要性
    • 15.如何学习STL

1.C/C++内存分布

栈又叫堆栈–非静态局部变量/函数参数/返回值等等,栈是向下增长的。

  1. 内存映射段是高效的I/O映射方式,用于装载一个共享的动态内存库。用户可使用系统接口创建共享共享内存,做进程间通信。(Linux课程如果没学到这块,现在只需要了解一下)

  2. 堆用于程序运行时动态内存分配,堆是可以上增长的。

  3. 数据段–存储全局数据和静态数据。

  4. 代码段–可执行的代码/只读常量

在这里插入图片描述

int globalVar = 1;
static int staticGlobalVar = 1;
void Test()
{
	static int staticVar = 1;
	int localVar = 1;
	int num1[10] = { 1, 2, 3, 4 };
	char char2[] = "abcd";
	const char* pChar3 = "abcd";
	int* ptr1 = (int*)malloc(sizeof(int) * 4);
	int* ptr2 = (int*)calloc(4, sizeof(int));
	int* ptr3 = (int*)realloc(ptr2, sizeof(int) * 4);
	free(ptr1);
	free(ptr3);
}

/*

. 选择题:
选项: A.栈 B.堆 C.数据段(静态区) D.代码段(常量区)
globalVar在哪里?__c__
staticGlobalVar在哪里?__c__
staticVar在哪里?__c__
localVar在哪里?__a__
num1 在哪里?___a_
char2在哪里?___a_
*char2在哪里?_a__
pChar3在哪里?__a__
*pChar3在哪里?__*pChar3指向的是abcd,abcd在常量区   D__
ptr1在哪里?__a__
*ptr1在哪里?__b__//malloc在堆上

*/
/*
全局数据和静态数据都在静态区
局部静态变量也是存在于静态区的

*/

在这里插入图片描述

2.C语言中动态内存管理方式:malloc/calloc/realloc/free

calloc会将开辟的空间初始化为0

void Test ()
{
// 1.malloc/calloc/realloc的区别是什么?
int* p2 = (int*)calloc(4, sizeof (int));
int* p3 = (int*)realloc(p2, sizeof(int)*10);
// 这里需要free(p2)吗?
free(p3 );
}

malloccallocrealloc 是 C 语言中用于动态内存分配的函数。它们的区别主要在于如何分配内存、初始化内存和调整已分配内存的大小。以下是它们的具体区别:

  1. malloc
  • 全称:Memory Allocation

  • 功能:分配指定字节大小的内存块,但不初始化内存。

  • 使用方式void* malloc(size_t size);

  • 返回值:返回指向分配内存块的指针,如果分配失败,返回 NULL

  • 特点:分配的内存内容是未定义的,可能包含垃圾值。

  1. calloc
  • 全称:Contiguous Allocation

  • 功能:分配一定数量的内存块,并将其初始化为零。

  • 使用方式void* calloc(size_t num, size_t size);

  • 返回值:返回指向分配内存块的指针,如果分配失败,返回 NULL

  • 特点:分配的内存是连续的,且所有位都被初始化为零。

  1. realloc
  • 全称:Reallocation

  • 功能:重新调整已分配内存的大小。可以扩展或缩小原有的内存块。

  • 使用方式void* realloc(void* ptr, size_t size);

  • 返回值:返回指向重新分配内存块的指针,如果重新分配失败,返回 NULL,并且原来的内存块保持不变。

  • 特点:如果扩大内存块,可能会移动到新的地址,并将原来的数据复制到新地址。缩小内存块则可能保留在原地址。

总结

  • 使用 malloc 时,内存内容是未初始化的;

  • 使用 calloc 时,内存内容会被初始化为零;

  • 使用 realloc 可以调整已分配内存的大小,可以根据需要扩展或缩小。

3.C++内存管理方式

new/delete操作内置类型

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

new在C++里面是个操作符/运算符

如果想申请一个整数,就直接new int

如果想初始化的话,这么写 new int(3)

如果想new多个int的话,后面跟方括号

void Test()
{
	// 动态申请一个int类型的空间
	int* ptr4 = new int;
	// 动态申请一个int类型的空间并初始化为10
	int* ptr5 = new int(10);
	// 动态申请10个int类型的空间
	int* ptr6 = new int[3];

	//如果是多个数组中的对象要初始化的话
	int* ptr7 = new int[3] {1, 2, 3};

	delete ptr4;
	delete ptr5;
	delete[] ptr6;
}

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

new和delete操作自定义类型

注意:申请和释放单个元素的空间,使用new和delete操作符,申请和释放连续的空间,使用new[]和delete[],注意:匹配起来使用。

内置类型用malloc还是new都是可以的,但是自定义类型就不一样了

自定义类型推荐使用new

malloc只会申请空间,但是new不仅会申请空间,还会调用构造函数

free只会释放空间,但是delete不仅会释放空间还可以调用析构函数


class A
{
public:
	A(int a = 0)
		: _a(a)
	{
		cout << "A():" << this << endl;
	}
	~A()
	{
		cout << "~A():" << this << endl;
	}
private:
	int _a;
};

struct ListNode//链表
{
	int _val;
	ListNode* _next;
	ListNode(int val)
		:_val(val)
		, _next(nullptr)
	{

	}
};
int main()
{
	//只申请空间
	A* p1 = (A*)malloc(sizeof(A));

	//用new就方便很多了
	//申请空间+构造函数
	A* p2 = new A(1);

	//只释放空间
	free(p1);

	//释放空间+析构函数
	delete p2;

	A* p6 = new A[10];//申请10个对象的空间
	//回调用10次构造函数
	delete[] p6;

	A aa1(1);
	A aa2(1);

	//A* p7 = new A[10]{ aa1,aa2 };
	A* p7 = new A[10]  {1,2,3};//直接使用隐式类型转换
	delete[] p7;
	 
	//在C语言的链表中我们通常需要写个buynode来申请一个节点
	//但是我们在C++中就不用了,我们直接new就行了
	ListNode* n1 = new ListNode(1);//申请空间并且调用ListNode的构造函数
	ListNode* n2 = new ListNode(2);
	ListNode* n3 = new ListNode(3);
	ListNode* n4 = new ListNode(4);

	n1->_next = n2;
	n2->_next = n3;
	n3->_next = n4;


	return 0;
}
//在一个类中一定要提供默认构造,不然就会出现很多的问题了

我们通过C++进行链表节点申请的时候我们可以直接通过new来进行申请空间和调用构造函数

就不用像c语言那样来写个函数进行节点的申请和初始化操作了

4.operator new与operator delete函数(重要点进行讲解)

new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间

operator new实际上是对malloc的一个封装

malloc失败之后返回一个空指针

operator new申请失败后会抛异常

在这里插入图片描述
operator new底层封装malloc

operator delete是和operator new进行配对的

通过上述两个全局函数的实现知道,operator new 实际也是通过malloc来申请空间,如果malloc申请空间成功就直接返回,否则执行用户提供的空间不足应对措施,如果用户提供该措施就继续申请,否则就抛异常。operator delete 最终是通过free来释放空间的。

5.new和delete的实现原理

内置类型

如果申请的是内置类型的空间,new和malloc,delete和free基本类似,不同的地方是: new/delete申请和释放的是单个元素的空间,new[]和delete[]申请的是连续空间,而且new在申请空间失败时会抛异常,malloc会返回NULL。

自定义类型

•new的原理

  1. 调用operator new函数申请空间

  2. 在申请的空间上执行构造函数,完成对象的构造

•delete的原理

  1. 在空间上执行析构函数,完成对象中资源的清理工作

  2. 调用operator delete函数释放对象的空间

•new T[N]的原理

  1. 调用operator new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请

  2. 在申请的空间上执行N次构造函数

•delete[]的原理

  1. 在释放的对象空间上执行N次析构函数,完成N个对象中资源的清理

  2. 调用operator delete[]释放空间,实际在operator delete[]中调用operator delete来释放空间

在这里插入图片描述

直接这样写,operator new和malloc的区别就是operator new失败了会抛异常,没有返回值

但这个不会调用构造函数,用法和malloc相似的

6.定位new表达式(placement-new) (了解)

定位new表达式是在已分配的原始内存空间中调用构造函数初始化一个对象

用格式:new (place_address) type或者new (place_address) type(initializer-list)

place_address必须是一个指针,initializer-list是类型的初始化列表

使用场景:定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

在这里插入图片描述
对p1指向的那块空间调用构造函数进行初始化操作

构造函数不支持显示调用,析构函数支持显示调用的

不要忘记释放,不要交错释放

7.malloc/free和new/delete的区别

malloc/free和new/delete的共同点是:都是从堆上申请空间,并且需要用户手动释放。不同的地方是:

  1. malloc和free是函数,new和delete是操作符

  2. malloc申请的空间不会初始化,new可以初始化

  3. malloc申请空间时,需要手动计算空间大小并传递,new只需在其后跟上空间的类型即可,如果是多个对象,[]中指定对象个数即可

  4. malloc的返回值为void*, 在使用时必须强转,new不需要,因为new后跟的是空间的类型

  5. malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常

  6. 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理释放

在项目中使用new我们是需要进行异常的捕获操作的

malloc需要强制转换,当时new是不需要强转的

8.泛型编程

//C++支持函数重载,允许函数名重复
void Swap(int& left, int& right)
{
	int temp = left;
	left = right;
	right = temp;
} 
void Swap(double& left, double& right)
{
	double temp = left;
	left = right;
	right = temp;
} 
void Swap(char& left, char& right)
{
	char temp = left;
	left = right;
	right = temp;
}

使用函数重载虽然可以实现,但是有一下几个不好的地方:1. 重载的函数仅仅是类型不同,代码复用率比较低,只要有新类型出现时,就需要用户自己增加对应的函数2. 代码的可维护性比较低,一个出错可能所有的重载均出错

9.函数模版

模版概念

函数模板代表了一个函数家族,该函数模板与类型无关,在使用时被参数化,根据实参类型产生函数的特定类型版本。

函数模版格式

template<typename T1, typename T2,…,typename Tn>返回值类型 函数名(参数列表){}

template英文翻译就是模版的意思

下面是一个交换函数的模版,可以对不同的类型进行一个交换的操作

template<typename T>
void Swap(T& left, T& right)//针对广泛的类型
{
	T temp = left;
	left = right;
	right = temp;
}
int main()
{
	int x = 0, y = 1;
	double m = 1.1, n = 2.2;
	//通过模版就很方便了
	//调用的其实还是两个函数
	Swap(x, y);
	Swap(m, n);

	return 0;
}

语法上面我们需要声明这个模版参数的类型template

模版的原理

函数模板是一个蓝图,它本身并不是函数,是编译器用使用方式产生特定具体类型函数的模具。所以其实模板就是将本来应该我们做的重复的事情交给了编译器,编译器成牛马了
在这里插入图片描述
在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。

函数模板的实例化

编译器通过模版生成对应的函数叫做实例化操作

实例化分为两种,一种叫做隐式实例化,一种叫做显式实例化

如果我们传的是两个类型不一样的数据的话是会报错的

,但是我们可以通过增加多个模版参数来进行不同类型数据的交换的

隐式实例化

在这里插入图片描述

在这里插入图片描述

template<typename T>//传递的是类型
void Swap(T& left, T& right)//定义的是对象
{
	T temp = left;
	left = right;
	right = temp;
}

template<class T1, class T2>//传递的是类型
void Swap(T1& left, T2& right)//定义的是对象
{
	T temp = left;
	left = right;
	right = temp;
}
int main()
{
	int x = 0, y = 1;
	double m = 1.1, n = 2.2;
	//通过模版就很方便了
	//调用的其实还是两个函数
	Swap(x, y);
	Swap(m, n);

	Swap(m, y);

	return 0;
}
//这两个实例化生成的函数构成重载了

在这里插入图片描述
像这种的话,我们如果传的是两种类型的数据的话,按照这个模版来,编译器是会报错的

但是我们是可以通过这个两个模版来解决这个问题的

还有一个方法,可以在传数据的时候将其中一个数据进行强制转换的操作

在这里插入图片描述

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.1, d2 = 20.1;
	Add(a1, a2);
	Add(d1, d2);

	
	cout << Add(a1, (int)d1)<< endl;//20
	cout << Add((double)a1,d1)<< endl;//20.1

	return 0;
}

显示实例化

在函数名和函数参数中间加上尖括号,括号之内写上要转换的类型

template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}
int main()
{
	int a1 = 10, a2 = 20;
	double d1 = 10.1, d2 = 20.1;

	//自动推导类型  隐式实例化
	Add(a1, a2);
	Add(d1, d2);

	
	cout << Add(a1, (int)d1)<< endl;//20
	cout << Add((double)a1,d1)<< endl;//20.1

	//在函数名和参数列表中间加上尖括号
	//这个叫做显示实例化
	cout <<  Add<int>(a1,d1) << endl;//20
	cout << Add<double>(a1, d1) << endl;//20.1


	return 0;
}

隐式实例化就是编译器进行一个自动推导,查看里面的数据类型

但是我们的显示实例化操作,我们直接显示的写出了我们要参与的数据的类型是什么

在这里插入图片描述
我们不知道传的类型是什么参数,对于这种的话我们就可以在传参的时候进行显式实例化操作了

编译器推不出来我们的数据是什么类型的,所以我们要显示的写出来这个参数的类型

如果模版函数和普通函数都存在的话我们是直接选择使用这个普通函数的,因为模版的话我们的编译器还要去推导这个T的类型,很麻烦,我们直接用普通的就行了

 int Add(int  left, int right)
{
	return left + right;
}


template<class T>
T Add(const T& left, const T& right)
{
	return left + right;
}

int main()
{
	Add(1, 2);
	return 0;
}

//我们这里有两个Add函数,那么调用的时候会先调用谁呢?
//模版和普通函数是可以同时存在的,但是我们是不知道会调用哪一个函数

//用模版其实比用普通函数更加麻烦的,因为编译器是需要对T进行一个推导的过程的
//有现成的就用现成的,就用普通函数

模版参数的匹配规则

1.一个非模板函数可以和一个同名的函数模板同时存在,而且该函数模板还可以被实例化为这个非模板函数

2.对于非模板函数和同名函数模板,如果其他条件都相同,在调动时会优先调用非模板函数而不会从该模板产生出一个实例。如果模板可以产生一个具有更好匹配的函数, 那么将选择模板

  1. 模板函数不允许自动类型转换,但普通函数可以进行自动类型转换

不同类型调用不同的函数或者模版


int Add(int  left, int right)
{
	return left + right;
}


template<class T>
T Add(const T& left, const T& right)
{
	return (left + right)*5;
}


template<class T1,class T2>
T1 Add( T1 left,  T2 right)
{
	return (left + right) * 10;
}

int main()
{
	cout << Add(1, 2) << endl;//调用普通函数
	//现在我们不想调用这个普通函数,我们想调用模版我们怎么解决呢?
	//我们显示实例化一下就行了
	//我们在这里显示实例化了,就是指明了编译器一定要使用模版
	cout << Add<int>(1, 2) << endl;//调用第一个模版
	cout << Add(1, 2) << endl;//调用第一个模版

	cout << Add(1, 2.2) << endl;//调用第二个模版


	return 0;
}

对于我们这里使用的Swap这个交换例子,我们以后直接使用swap进行交换操作,这个函数是已经在库里面存在了

10.类模版


template<class T1, class T2>
class 类模板名
{
	// 类内成员定义
};

#include<iostream>
using namespace std;

using STDataType = int;

// 类模版
//template<typename T>
class Stack
{
	
public :
	Stack(size_t capacity = 4)
	{
		_array = new STDataType[capacity];
		_capacity = capacity;
		_size = 0;
	} 
private:
	STDataType* _array;
	size_t _capacity;
	size_t _size;
};

int main()
{
	//现在我们想往两个栈分别存入不同类型的数据
	//如果使用我们的这个using STDataType = int;是不能解决问题的

	Stack st1;//存int
	Stack st2;//存double

	return 0;
}

using STDataType = int;还是不能解决同时处理不同类型的数据的

还是得使用到我们的模版了

实例化生成对应的类,这里是两个不同的类型

// 类模版
template<typename T>
class Stack
{

public:
	Stack(size_t capacity = 4)
	{
		_array = new T[capacity];
		_capacity = capacity;
		_size = 0;
	}
private:
	T* _array;
	size_t _capacity;
	size_t _size;
};

int main()
{
	//现在我们想往两个栈分别存入不同类型的数据
	//如果使用我们的这个using STDataType = int;是不能解决问题的

	//我们的类模版是不能隐式实例化操作的
	//只能显示实例化操作

	//实例化生成对应的类,这里是两个不同的类型
	Stack<int> st1;//存int
	Stack<double> st2;//存double

	return 0;
}

模版不建议声明和定义分离到两个文件.h 和.cpp会出现链接错误

只有在类里面我们才能使用这个T,出了这个类就不作数了

所以声明和定义不能分离

声明和定义分离的写法错误写法:

// 类模版
template<typename T>
class Stack
{

public:
	Stack(size_t capacity = 4)
	{
		_array = new T[capacity];
		_capacity = capacity;
		_size = 0;
	}
	
	void Push(const T& data);
private:
	T* _array;
	size_t _capacity;
	size_t _size;
};
void Stack::Push(const T& data)
{
	// 扩容
	_array[_size] = data;
	++_size;
}

声明和定义分离的写法正确写法:

// 类模版
template<typename T>
class Stack
{

public:
	Stack(size_t capacity = 4)
	{
		_array = new T[capacity];
		_capacity = capacity;
		_size = 0;
	}
	
	void Push(const T& data);
private:
	T* _array;
	size_t _capacity;
	size_t _size;
};
template<typename T>
void Stack<T>::Push(const T& data)
{
	// 扩容
	_array[_size] = data;
	++_size;
}

要制定类域和类名

类模板实例化与函数模板实例化不同,类模板实例化需要在类模板名字后跟<>,然后将实例化的类型放在<>中即可,类模板名字不是真正的类,而实例化的结果才是真正的类

Stack是类名,Stack才是类型


// Stack是类名,Stack<int>才是类型
Stack<int> st1; // int
Stack<double> st2; // double

11.什么是STL

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。

12.STL的版本

原始版本

Alexander Stepanov、Meng Lee 在惠普实验室完成的原始版本,本着开源精神,他们声明允许任何人任意运用、拷贝、修改、传播、商业使用这些代码,无需付费。唯一的条件就是也需要向原始版本一样做开源使用。 HP 版本–所有STL实现版本的始祖。

P. J. 版本

由P. J. Plauger开发,继承自HP版本,被Windows Visual C++采用,不能公开或修改,缺陷:可读性比较低,符号命名比较怪异。

RW版本

由Rouge Wage公司开发,继承自HP版本,被C+ + Builder 采用,不能公开或修改,可读性一般。

SGI版本

由Silicon Graphics Computer Systems,Inc公司开发,继承自HP版 本。被GCC(Linux)采用,可移植性好,可公开、修改甚至贩卖,从命名风格和编程 风格上看,阅读性非常高。我们后面学习STL要阅读部分源代码,主要参考的就是这个版本

13.STL的六大组件

在这里插入图片描述

14.STL的重要性

在这里插入图片描述

15.如何学习STL

在这里插入图片描述

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

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

相关文章

Redis主从复制机制详解

目录 一、主从复制介绍二、搭建主从复制三、主从复制流程四、关于Replication ID五、主从复制核心知识六、主从复制应用场景七、主从复制的注意事项 一、主从复制介绍 1、什么是主从复制&#xff1f; 2、为什么要使用主从复制&#xff1f; redis-server单点故障。单节点QPS…

MyBatis XML映射文件

XML映射文件 XML映射文件的名称与Mapper接口名称一致&#xff0c;并且将XML映射文件和Mapper接口放置在相同包下&#xff08;同包同名&#xff09;XML映射文件的namespace属性为Mapper接口全限定名一致XML映射文件中SQL语句的id与Mapper接口中的方法名一致&#xff0c;并保持返…

MBI6665Q升降压LED驱动芯片车规级AEC-Q100

MBI6665Q是由聚积科技&#xff08;Macroblock Inc.&#xff09;开发的一款多拓扑恒流LED驱动器&#xff0c;主要用于汽车照明应用。凭借其强大的功能集&#xff0c;MBI6665Q可以满足高效照明解决方案的需求&#xff0c;广泛应用于日间行车灯&#xff08;DRL&#xff09;、雾灯等…

idea的maven组件管理依赖小规则

pom文件引入一个依赖&#xff0c;idea会先找到依赖&#xff0c;然后才更新界面&#xff0c;如果找不到&#xff0c;不会更新界面&#xff0c;除非指定正确的版本才会更新界面&#xff0c;更新界面后&#xff0c;再次指定一个错误的版本&#xff0c;idea不会更新界面&#xff0c…

海康大华等厂家摄像头、执法记录仪等通过GB28181注册到LiveGBS平台,如何实时获取设备和通道的在线状态

LiveGBS如何订阅设备状态在线离线状态redis订阅设备或是通道状态subscribe device操作及示例 1、如何监听设备状态2、device订阅2.1、设备上线消息2.2、设备离线消息2.2、通道上线消息2.2、通道离线消息 3、订阅示例3.1、连接REDIS3.2、订阅device示例3.3、设备上线示例3.3.1、…

2014年国赛高教杯数学建模B题创意平板折叠桌解题全过程文档及程序

2014年国赛高教杯数学建模 B题 创意平板折叠桌 某公司生产一种可折叠的桌子&#xff0c;桌面呈圆形&#xff0c;桌腿随着铰链的活动可以平摊成一张平板&#xff08;如图1-2所示&#xff09;。桌腿由若干根木条组成&#xff0c;分成两组&#xff0c;每组各用一根钢筋将木条连接…

【SpringBoot详细教程】-13-SpringBoot整合事务管理 【持续更新】

Hello&#xff0c;大胸弟们&#xff0c;我们又又又见面了&#xff0c;今天攀哥继续为大家分享一下SpringBoot的教程&#xff0c;没点关注的宝宝&#xff0c;点一下关注。 &#x1f332; 事务管理的意义 &#x1f33f; 身边事务的案例&#xff1a; 桃子向好友攀哥汇款5000元…

STL之set、map的使用

STL之set、map 1. 序列式容器和关联式容器2. set系列的使⽤参考文档链接&#xff1a;2.1 set的介绍&#xff08;2&#xff09;set的增删查2.2 multiset的介绍 3 map3.1 参考文档3.2 map类的介绍3.3 pair类型介绍3.4 map的构造3.6 map的数据修改3.7 multimap和map的差异 1. 序列…

鸿蒙next 电商实战项目 来了

前言&#xff1a; 最新在学习鸿蒙next 开发 就写了一个demo 今天就分享给大家一下 效果图 客户端实现 1 底部导航器实现 import choice from ../view/ChoicePage import HomePage from ../view/HomePage import MyPage from ../view/MyPage import Shoppingcar from ../view…

【Canvas与诗词】要做一棵树,站成永恒

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>要做一棵树站成永恒</title><style type"text/css&quo…

电阻负载柜的工作原理是什么?

电阻负载柜是用于模拟电力系统中各种负载的设备&#xff0c;它可以模拟实际负载的各种特性&#xff0c;如阻性、感性和容性负载。电阻负载柜在电力系统、电气设备测试和维护等领域具有广泛的应用。其工作原理主要包括以下几个方面&#xff1a; 电阻负载柜的核心部分是电阻元件…

根据请求错误的状态码判断代理配置问题

SafeLine&#xff0c;中文名 “雷池”&#xff0c;是一款简单好用, 效果突出的 Web 应用防火墙(WAF)&#xff0c;可以保护 Web 服务不受黑客攻击。 雷池通过过滤和监控 Web 应用与互联网之间的 HTTP 流量来保护 Web 服务。可以保护 Web 服务免受 SQL 注入、XSS、 代码注入、命…

后端——eclipse实现前端后端的交互(1)

1.创建Web Project 首先&#xff0c;为实现前端后端交互&#xff0c;要将HTML文件和Java后端文件放入eclipse。 右键—>New—>Project—>选择“Dynamic Web Project” 创建完成 这里我们会看到报了一个错&#xff1a; Description Resource Path Location Typ…

GC1262E替代APX9262S/茂达芯片在笔记本和显卡风散热风扇中的应用分享

随着移动计算和高性能图形处理技术的不断进步&#xff0c;笔记本电脑和显卡的散热需求日益增加。散热风扇作为关键组件&#xff0c;其控制芯片的选择对系统性能和用户体验有着直接影响。本文将探讨芯麦的GC1262E芯片如何替代APX9262S/茂达芯片&#xff0c;应用于笔记本和显卡的…

持续研发赋能,强达电路具备多项核心技术

深圳市强达电路股份有限公司&#xff08;以下简称&#xff1a;强达电路或公司&#xff09;深耕PCB行业二十年&#xff0c;主营业务为PCB的研发、生产和销售&#xff0c;是一家主要专注于中高端样板和小批量板产品的PCB企业。公司2004年创立于深圳&#xff0c;抓住国内早期缺少中…

面试宝典:揭秘50个大型模型核心问题精选

我精选50个大模型高频面试题&#xff0c;分享给大家 简述GPT和BERT的区别讲一下GPT系列模型是如何演进的&#xff1f;为什么现在的大模型大多是decoder-only的架构&#xff1f;讲一下生成式语言模型的工作机理哪些因素会导致LLM的偏见&#xff1f;LLM中的因果语言建模与掩码语…

【问题实战】Jmeter中jtl格式转换图片后如何分开展示各个性能指标?

【问题实战】Jmeter中jtl格式转换图片后如何分开展示各个性能指标&#xff1f; 遇到的问题解决方法查看修改效果 遇到的问题 JMeter测试计划中只设置了一个性能监控器jpgc - PerfMon Metrics Collector&#xff1b;在这个监控器中设置几个性能监控指标&#xff0c;比如CPU、Di…

电脑快速切换IP地址命令是什么?详解与实践

有时&#xff0c;出于安全考虑或测试需要&#xff0c;我们可能需要快速切换电脑的IP地址。虽然这一过程在初学者看来可能略显复杂&#xff0c;但通过简单的命令和步骤&#xff0c; 即使是普通用户也能轻松实现。本文将详细介绍在Windows系统中快速切换IP地址的几种方法&#xf…

无人自助超市系统小程序源码开发

随着科技的飞速发展和消费模式的转变&#xff0c;无人自助超市作为一种新兴的商业模式&#xff0c;以其便捷性、高效率以及对“体验式购物”的完美诠释&#xff0c;受到了广泛关注。本文renxb001将深入探讨无人自助超市系统小程序源码开发的核心环节和技术要点。 一、系统需求分…

【北京迅为】《STM32MP157开发板嵌入式开发指南》- 第172章 使用C文件编写I2C client代码

iTOP-STM32MP157开发板采用ST推出的双核cortex-A7单核cortex-M4异构处理器&#xff0c;既可用Linux、又可以用于STM32单片机开发。开发板采用核心板底板结构&#xff0c;主频650M、1G内存、8G存储&#xff0c;核心板采用工业级板对板连接器&#xff0c;高可靠&#xff0c;牢固耐…