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

在这里插入图片描述

本文

    • 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类型的空间并初始化为10int* 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;//20cout << Add((double)a1,d1)<< endl;//20.1return 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;//20cout << Add((double)a1,d1)<< endl;//20.1//在函数名和参数列表中间加上尖括号//这个叫做显示实例化cout <<  Add<int>(a1,d1) << endl;//20cout << Add<double>(a1, d1) << endl;//20.1return 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;//存intStack st2;//存doublereturn 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;//存intStack<double> st2;//存doublereturn 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.mzph.cn/diannao/55964.shtml

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

相关文章

制造业DT数字化之生产制造业务建模

一、工厂建模为何物&#xff1f; 对制造业人员&#xff08;人&#xff09;、设备&#xff08;机&#xff09;、材料&#xff08;料&#xff09;、工艺流程&#xff08;法&#xff09;、工厂环境&#xff08;环&#xff09;数据化管理的过程就叫工厂建模。 二、制造建模有哪几大…

【操作系统】引导(Boot)电脑的奇妙开机过程

&#x1f339;&#x1f60a;&#x1f339;博客主页&#xff1a;【Hello_shuoCSDN博客】 ✨操作系统详见 【操作系统专项】 ✨C语言知识详见&#xff1a;【C语言专项】 目录 什么是操作系统的引导&#xff1f; 操作系统的引导&#xff08;开机过程&#xff09; Windows操作系…

QD1-P2 HTML 编辑器:HBuilderX

本节学习&#xff1a; HTML课程内容介绍HBuilderX编辑器的使用 本节视频 www.bilibili.com/video/BV1n64y1U7oj?p2 HTML 内容 基础语法 标签整体架构DOCTYPE 常用标签 标题和水平线段落和换行列表div 和 span格式化标签图片超链接标签表格表单字符实体 编辑器 HBuilder…

设计测试用例的方法

目录 1、等价类 2、边界值 3、场景法 4、正交表法 5、设计正交表 6、判定表法 7、错误猜想法 1、等价类 在测试中选取一些数据作为等价类进行测试&#xff0c;如果测试通过&#xff0c;就代表测试通过&#xff0c;可以用少量代表性的测试数据取得较好的测试结果。 等价类…

智能扭矩系统在轨道交通行业的应用_SunTorque

【大家好&#xff0c;我是唐Sun&#xff0c;唐Sun的唐&#xff0c;唐Sun的Sun。一站式数智工厂解决方案服务商】 在现代轨道交通领域&#xff0c;安全、高效和可靠性是至关重要的考量因素。智能扭矩系统作为一项先进的技术&#xff0c;正逐渐在轨道交通行业中展现出其重要的应用…

【原创】java+springboot+mysql劳动教育网系统设计与实现

个人主页&#xff1a;程序猿小小杨 个人简介&#xff1a;从事开发多年&#xff0c;Java、Php、Python、前端开发均有涉猎 博客内容&#xff1a;Java项目实战、项目演示、技术分享 文末有作者名片&#xff0c;希望和大家一起共同进步&#xff0c;你只管努力&#xff0c;剩下的交…

使用Milvus和Llama-agents构建更强大的Agent系统

代理&#xff08;Agent&#xff09;系统能够帮助开发人员创建智能的自主系统&#xff0c;因此变得越来越流行。大语言模型&#xff08;LLM&#xff09;能够遵循各种指令&#xff0c;是管理 Agent 的理想选择&#xff0c;在许多场景中帮助我们尽可能减少人工干预、处理更多复杂任…

C++与Java Web开发的对比分析:优势与差异

目录 1. 引言 2. C的开发优势与特点 2.1 高性能与硬件控制 2.2 面向对象与多范式支持 2.3 跨平台能力 3. Java Web的开发优势与特点 3.1 跨平台与广泛的企业应用 3.2 丰富的生态系统与工具支持 3.3 安全性与稳定性 4. C与Java Web的差异对比 4.1 性能与效率 4.2 开发…

基于go开发的终端版即时通信系统(c-s架构)

项目架构图 类似一个聊天室一样 整体是一个客户端和服务端之间的并发多线程网络通信&#xff0c;效果可以翻到最后面看。 为了巩固基础的项目练手所以分为9个阶段进行迭代开发 版本⼀&#xff1a;构建基础Server 新建一个文件夹就叫golang-IM_system 第一阶段先将server的大…

LLM | Tokenization 从原理与代码了解GPT的分词器

声明&#xff1a;以上内容全是学习Andrej Karpathy油管教学视频的总结。 --------------------------------------------------------------------------------------------------------------------------------- 大家好。在今天我们学习llm中的Tokenization&#xff0c;即分…

使离医院最远的村庄到医院的路程最短

给定n个村庄之间的交通图&#xff0c;若村庄i和j之间有道路&#xff0c;则将顶点i和j用边连接&#xff0c;边上的Wij表示这条道路的长度&#xff0c;现在要从这n个村庄中选择一个村庄建一所医院&#xff0c;问这所医院应建在哪个村庄&#xff0c;才能使离医院最远的村庄到医院的…

HCIP--以太网交换安全(三)MAC地址漂移防止与检测

MAC地址漂移防止与检测 一、MAC地址漂移防止与检测知识点 1.1MAC地址漂移的概述 MAC地址漂移是指交换机上一个vlan内有两个端口学习到同一个MAC地址&#xff0c;后学习到的MAC地址表项覆盖原MAC地址表项的现象。 1.2.MAC地址漂移的防止方法 &#xff08;1&#xff09;配置…

Windows7 X64 成功安装 .NET Framework 4.8 的两种方法

Windows7 X64 成功安装 .NET Framework 4.8 的两种方法 windows7系统SP1安装完成后&#xff0c;在安装某软件时&#xff0c;提示需要先安装4.6以上的版本net-framework包&#xff0c;正好电脑里有个net-framework4.8软件包&#xff0c;于是打算用上&#xff0c;可是在安装时&a…

Github 2024-10-11 Java开源项目日报 Top9

根据Github Trendings的统计,今日(2024-10-11统计)共有9个项目上榜。根据开发语言中项目的数量,汇总情况如下: 开发语言项目数量Java项目9TypeScript项目1Vue项目1C++项目1JeecgBoot 企业级低代码开发平台 创建周期:2062 天开发语言:Java, Vue协议类型:Apache License 2.…

LabVIEW激光诱导击穿光谱识别与分析系统

LabVIEW激光诱导击穿光谱&#xff08;LIBS&#xff09;分析系统利用高能量脉冲激光产生高温等离子体&#xff0c;通过分析等离子体发出的光谱来定性分析样品中的元素种类。该系统的开发集成了软件与硬件的设计&#xff0c;实现了自动识别和定性分析功能&#xff0c;适用于环境监…

OpenCV 之 实现基于Lucas-Kanade算法的光流追踪

引言 在计算机视觉中&#xff0c;光流是指物体、场景或摄像机之间的相对运动造成的像素变化。光流估计是计算机视觉中的一个基础课题&#xff0c;广泛应用于许多领域&#xff0c;比如自动驾驶汽车、机器人导航、手势识别等。OpenCV是一个开源的计算机视觉库&#xff0c;提供了…

计算机网络:计算机网络概述 —— 描述计算机网络的参数

文章目录 数据量性能指标速率带宽数据传输速率 吞吐量时延分析时延问题 时延带宽积往返时间利用率丢包率丢包的情况 抖动可用性可靠性安全性 计算机网络是现代信息社会的基础设施&#xff0c;其性能和可靠性对各类应用至关重要。为了理解和优化计算机网络&#xff0c;我们需要深…

vue后台管理系统从0到1(1)

文章目录 vue后台管理系统从0到1&#xff08;1&#xff09;nvm 下载安装1.卸载nodejs环境2.安装nvm 安装nrm vue后台管理系统从0到1&#xff08;1&#xff09; 第一节主要是先安装我们的工具nvm nodejs版本管理工具&#xff0c;和nrm镜像管理工具 nvm 下载安装 nvm是一款管理…

重学SpringBoot3-集成Redis(一)之基础功能

更多SpringBoot3内容请关注我的专栏&#xff1a;《SpringBoot3》 期待您的点赞&#x1f44d;收藏⭐评论✍ 重学SpringBoot3-集成Redis&#xff08;一&#xff09;之基础功能 1. 项目初始化2. 配置 Redis3. 配置 Redis 序列化4. 操作 Redis 工具类5. 编写 REST 控制器6. 测试 AP…

论文翻译 | Language Models are Few-Shot Learners 语言模型是少样本学习者(上)

摘要 最近的工作表明&#xff0c;通过在大规模文本语料库上进行预训练&#xff0c;然后在特定任务上进行微调&#xff0c;许多自然语言处理&#xff08;NLP&#xff09;任务和基准测试都取得了显著的提升。尽管这种方法在架构上通常是任务无关的&#xff0c;但它仍然需要成千上…