【剖析STL】String

news2024/11/16 9:39:28

在这里插入图片描述

1.什么是STL?

标准模板库(Standard Template Library,STL)是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。虽说它主要出现到C++中,但在被引入C++之前该技术就已经存在了很长时间。STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。

  • 🔥标准模板库是一个C++软件库,大量影响了C++标准程序库但并非是其的一部分。其中包含4个组件,分别为算法、容器、函数、迭代器。

  • 🔥模板是C++程序设计语言中的一个重要特征,而标准模板库正是基于此特征。标准模板库使得C++编程语言在有了同Java一样强大的类库的同时,保有了更大的可扩展性。

image-20230508162229893

1.1STL的缺陷:

  1. STL库的更新太慢了。这个得严重吐槽,上一版靠谱是C++98,中间的C++03基本一些修订。C++11出
    来已经相隔了13年,STL才进一步更新。
  2. STL现在都没有支持线程安全。并发环境下需要我们自己加锁。且锁的粒度是比较大的。
  3. STL极度的追求效率,导致内部比较复杂。比如类型萃取,迭代器萃取。
  4. STL的使用会有代码膨胀的问题,比如使用vector/vector/vector这样会生成多份代码,当然这是模板语
    法本身导致的。

2.Stirng容器

2.1为什么需要学习String容器?

C语言中,字符串是以’\0’结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数,
但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理,稍不留神可
能还会越界访问。

为了优化这个问题,我们引入了String容器。

2.2初始String:

string本身是一个类模板:

image-20230508170154430

string就是char类型的数组,char类型一个字节

wstring是wchar类型的数组,wchar为两个字节

char16_t类型为2字节,char32_t为4个字节

image-20230508170222533

  • 🔥string是表示字符串的字符串类
  • 🔥该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。
  • 🔥string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator>
    string;
  • 🔥不能操作多字节或者变长字符的序列。在使用string类时,必须包含#include头文件以及using namespace std;

image-20230508165644704

2.3String类的常用接口说明(注意下面我只讲解最常用的接口)

2.3.1string类对象的常见构造:

  • Strin在C++98下有以下几种构造函数:

image-20230508172119160

第二种: string s3 = "hello world";

这里是一个const char*类型隐式转换成string类型

第三种: string s4(s3, 6, 3);

子字符串构造函数

  • 🔥复制str中从字符位置pos开始并跨越len个字符的部分(如果str太短或len为string::npos,则复制到str的末尾)。

  • 🔥第三个参数有缺省值,npos是无符号整形,-1代表整形最大值为42亿多

image-20230411143814898

string s1;
	string s2("hello world");
	string s3 = "hello world";
	string s4(s3, 6, 3);

	string s5(s3, 6, 13);
	cout << s5 << endl;

	string s6(s3, 6);
	cout << s6 << endl;

	string s7("hello world", 5);
	cout << s7 << endl;

	string s8(10, '*');
	cout << s8 << endl;

  • 本部分会详细介绍以下几个构造函数:
(constructor)函数名称功能说明
string() (重点)构造空的string类对象,即空字符串
string(const char* s) (重点)用C-string来构造string类对象
string(size_t n, char c)string类对象中包含n个字符c
string(const string&s) (重点)拷贝构造函数
  • string() (重点):

构造空的string类对象,即空字符串

这里的空字符串指的是连\0都没有的

string s1(""); string s2();

  • 🔥s1是只有\0,s2是连\0都没有,s1的size和length都为0,capacity为15,s2没有size和length和capacity

image-20230508195519139

  • string(const char* s) (重点):

复制以s为指向的以空结尾的字符序列(C-string)。

int main()
{
	const char* p = "aaaaa";
	string s1(p);
	cout <<s1 << endl;//aaaaa
	return 0;
}
  • string(size_t n, char c):

用字符c的n个连续副本填充字符串。

string s2(4, 'b'); cout << s2 << endl;//bbbb

image-20230508174642814

  • string(const string&s) (重点)

构造一个str的副本。

string s3(s2);

2.3.2string类对象的容量操作

  • 本部分会介绍以下几个容器操作:
函数名称功能说明
size(重点)返回字符串有效字符长度
length返回字符串有效字符长度
capacity返回空间总大小
empty (重点)检测字符串释放为空串,是返回true,否则返回false
clear (重点)清空有效字符
reserve (重点)为字符串预留空间**
resize (重点)将有效字符的个数该成n个,多出的空间用字符c填充
  • size和length

size和length的效果是一样的,都是返回字符串的有效长度(不包括\0)

注意

size()与length()方法底层实现原理完全相同,引入size()的原因是为了与其他容器的接口保持一
致,一般情况下基本都是用size()。

  • capacity

image-20230508191415653

  • 🔥返回当前为字符串分配的存储空间的大小,以字节表示。

这个容量不一定等于字符串长度。它可以等于或大于,额外的空间允许对象在向字符串中添加新字符时优化其操作。

  • 🔥注意,这个容量并没有假设字符串的长度有限制。当此容量耗尽并且需要更多容量时,对象会自动对其进行扩展(重新分配其存储空间)。字符串长度的理论限制由成员max_size给出。

在对象被修改的任何时候,字符串的容量都可以被改变,即使这种修改意味着减小大小或者容量没有耗尽(这与vector容器中对容量的保证相反)。

可以通过调用成员reserve(后面会介绍)显式地更改字符串的容量。

void Teststring1()
{
	// 注意:string类对象支持直接用cin和cout进行输入和输出
	string s("hello, xiaolu!!!");
	cout << s.size() << endl;//13
	cout << s.length() << endl;//13
	cout << s.capacity() << endl;//15
	cout << s << endl;
}
  • 在Debug和Release版本下,编译器自动扩容情况:
void TestPushBack()
{
	string s;
	size_t sz = s.capacity();
	cout << "making s grow:\n";
	cout << "capacity changed: " << sz << '\n';
	for (int i = 0; i < 100; ++i)
	{
		s.push_back('c');
		if (sz != s.capacity())
		{
			sz = s.capacity();
			cout << "capacity changed: " << sz << '\n';
		}
	}
}

在debug和release版本下,我们发现编译器每次扩容1.5倍左右

image-20230509000626071

  • clear

clear()只是将string中有效字符清空,不改变底层空间大小。

这里的情况是指清空size和length,不改变capacity

image-20230508192051242

void Teststring1()
{
	// 注意:string类对象支持直接用cin和cout进行输入和输出
	string s("hello, xiaolu!!!");
	cout << s.size() << endl;//13
	cout << s.length() << endl;//13
	cout << s.capacity() << endl;//15
	cout << s << endl;

	// 将s中的字符串清空,注意清空时只是将size清0,不改变底层空间的大小
	s.clear();
	cout << s.size() << endl;//0
	cout << s.capacity() << endl;//15
}
  • resize (重点)

image-20230508192501923

  • 🔥将字符串大小调整为n个字符的长度。

如果n小于当前字符串长度,则将当前值缩短到前n个字符,删除第n个字符以外的字符。

如果n大于当前字符串长度,则通过在末尾插入尽可能多的字符来扩展当前内容,以达到n的大小。如果指定了c,则新元素被初始化为c的副本,否则,它们是值初始化的字符(空字符)。

  • 🔥这里如果缩小有效字符,只改变size和length,不改变capacity
void Teststring1()
{
	// 注意:string类对象支持直接用cin和cout进行输入和输出
	string s("hello, xiaolu!!!");
	s.clear();
	cout << s.size() << endl;//0
	cout << s.capacity() << endl;//15

	// 将s中有效字符个数增加到10个,多出位置用'a'进行填充
	// “aaaaaaaaaa”
	s.resize(10, 'a');
	cout << s.size() << endl;//10
	cout << s.capacity() << endl;//15

	// 将s中有效字符个数增加到15个,多出位置用缺省值'\0'进行填充
	// "aaaaaaaaaa\0\0\0\0\0"
	// 注意此时s中有效字符个数已经增加到15个
	s.resize(15);
	cout << s.size() << endl;//15
	cout << s.capacity() << endl;//15
	cout << s << endl;

	// 将s中有效字符个数缩小到5个
	s.resize(5);
	cout << s.size() << endl;//5
	cout << s.capacity() << endl;//15
	cout << s << endl;
}
  • reserve (重点)

image-20230508193706796

  • 🔥reserve(size_t res_arg=0):为string预留空间,不改变有效元素个数,当reserve的参数小于
    string的底层空间总大小时,reserver不会改变容量大小。
  • 🔥 利用reserve提高插入数据的效率,避免增容带来的开销
void Teststring2()
{
	string s;
	// 测试reserve是否会改变string中有效元素个数
	s.reserve(100);
	cout << s.size() << endl;//0
	cout << s.capacity() << endl;//111

	// 测试reserve参数小于string的底层空间大小时,是否会将空间缩小
	s.reserve(50);
	cout << s.size() << endl;//0
	cout << s.capacity() << endl;//111
}
  • empty

image-20230508194723919

这里必须要对象存在才可以调用,像string()出来的对象不存在,根本调用不了

image-20230508200143646

2.3.3string类对象的访问及遍历操作

函数名称功能说明
operator[] (重点)返回pos位置的字符,const string类对象调用
begin+ endbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭
代器
rbegin + rendbegin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭
代器
范围forC++11支持更简洁的范围for的新遍历方式
  • operator[] (重点)

我们在用字符数组的时候,我们经常用[]来访问字符,我们在stirng中同样可以这样使用

image-20230509001335100

  • 范围for

C++11支持更简洁的范围for的新遍历方式

void Teststring4()
{
	string s("hello xiaolu");
	for (size_t i = 0; i < s.size(); ++i)
		cout << s[i] << " ";
	cout << endl;
	for (auto ch : s)
		cout << ch << " ";
}
  • 迭代器和反向迭代器

迭代器(iterable)是一个超级接口! 是可以遍历集合的对象,为各种容器提供了公共的操作接口,隔离对容器的遍历操作和底层实现,从而解耦。

  • 🔥迭代器应该有4种,正向,反向,正向const,反向const

迭代器可以近似理解为指针,后面会详细讲解的

begin返回指向字符串开头的迭代器。

  • 🔥如果string对象是const限定的,该函数返回一个const_iterator。否则,它返回一个迭代器。

❓这里的const跟我们之前的const int i是不是一样的?

💡并不是,后者是一个关键字被修饰的不可以修改,前置是一个类型名称,被修饰的是这个迭代器指向的内容

end返回一个指向字符串末尾字符的迭代器。

rbegin和rend 跟begin和end完全相反

image-20230509004957501

void Teststring4()
{
	string s("hello xiaolu");
	string::iterator it = s.begin();
	while (it != s.end())
	{
		cout << *it << " ";
		++it;
	}
	cout << endl;

	// string::reverse_iterator rit = s.rbegin();
	// C++11之后,直接使用auto定义迭代器,让编译器推到迭代器的类型
	auto rit = s.rbegin();
	while (rit != s.rend())
	{
		cout << *rit << " ";
		++rit;
	}
	cout << endl;
}

2.3.4string类对象的修改操作

函数名称功能说明
push_back在字符串后尾插字符c
append在字符串后追加一个字符串
operator+= (重点)在字符串后追加字符串str
c_str(重点)返回C格式字符串
find + npos(重点)从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置
rfind从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置
substr在str中从pos位置开始,截取n个字符,然后将其返回
  • push_back

将字符c添加到字符串的末尾,使其长度增加1。

string str; str.push_back(' '); // 在str后插入空格

  • append

image-20230509084816554

追加到字符串

通过在当前值的末尾添加额外的字符来扩展字符串:

void Teststring5()
{
	string str;
	str.push_back(' ');   // 在str后插入空格
	str.append("hello");  // 在str后追加一个字符"hello"
}
  • operator+= (重点)

在字符串后追加字符串str

void Teststring5()
{
	string str;
	str.push_back(' ');   // 在str后插入空格
	str.append("hello");  // 在str后追加一个字符"hello"
	str += 'x';           // 在str后追加一个字符'x'   
	str += "iaolu";          // 在str后追加一个字符串"iaolu"
	cout << str << endl;
	}
  • c_str(重点)

image-20230509090337304

获取C字符串等价项

  • 🔥返回一个指向数组的指针,该数组包含一个以空字符结尾的字符序列(即C-string),表示string对象的当前值。
void Teststring5()
{
	string str;
	str.push_back(' ');   // 在str后插入空格
	str.append("hello");  // 在str后追加一个字符"hello"
	str += 'x';           // 在str后追加一个字符'x'   
	str += "iaolu";          // 在str后追加一个字符串"iaolu"
	cout << str << endl;
	cout << str.c_str() << endl;   // 以C语言的方式打印字符串
	}
  • find + npos(重点)

image-20230509090928480

在字符串中搜索由其参数指定的序列的第一个匹配项。

  • 🔥当指定pos时,搜索只包含pos位置或之后的字符,忽略任何可能包含pos之前字符的情况。

  • 🔥请注意,与find_first_of成员不同的是,每当搜索多个字符时,仅匹配其中一个字符是不够的,必须匹配整个序列。

  • rfind

跟find完全相反,她从pos位置开始向前走

当指定pos时,搜索只包含从pos位置开始或之前的字符序列,忽略任何从pos位置之后开始的可能匹配。

  • substr

image-20230509091625581

生成子串,返回一个新构造的string对象,其值初始化为该对象的子字符串的副本。

  • 🔥子字符串是对象的一部分,从字符位置pos开始,跨越len字符(或直到字符串末尾,以哪个先到哪个)。
void Teststring5()
{
	string str;
	str.push_back(' ');   // 在str后插入空格
	str.append("hello");  // 在str后追加一个字符"hello"
	str += 'x';           // 在str后追加一个字符'x'   
	str += "iaolu";          // 在str后追加一个字符串"iaolu"
	cout << str << endl;
	cout << str.c_str() << endl;   // 以C语言的方式打印字符串

	// 获取file的后缀
	string file("string.cpp");
	size_t pos = file.rfind('.');
	string suffix(file.substr(pos, file.size() - pos));
	cout << suffix << endl;

	// npos是string里面的一个静态成员变量
	// static const size_t npos = -1;

	// 取出url中的域名
	string url("http://www.cplusplus.com/reference/string/string/find/");
	cout << url << endl;//http://www.cplusplus.com/reference/string/string/find/
	size_t start = url.find("://");
	if (start == string::npos)
	{
		cout << "invalid url" << endl;
		return;
	}
	start += 3;
	size_t finish = url.find('/', start);
	string address = url.substr(start, finish - start);
	cout << address << endl;//www.cplusplus.com

	// 删除url的协议前缀
	pos = url.find("://");
	url.erase(0, pos + 3);
	cout << url << endl;
}

注意:

  • 🔥在string尾部追加字符时,s.push_back© / s.append(1, c) / s += 'c’三种的实现方式差不多,一般
    情况下string类的+=操作用的比较多,+=操作不仅可以连接单个字符,还可以连接字符串。
  • 🔥对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好。

2.3.5string类非成员函数

函数功能说明
operator+尽量少用,因为传值返回,导致深拷贝效率低
operator>> (重点)输入运算符重载
operator<< (重点)输出运算符重载
getline (重点)获取一行字符串
relational operators (重点)relational operators (重点)
  • operator+

连接字符串,返回一个新构造的string对象,其值由lhs中的字符和rhs中的字符拼接而成。

  • getline (重点)

image-20230509095334545

getline(istream& is, string& str, char delim);

  • 🔥这个形式的函数从输入流is中读取一行文本,并将其存储在str字符串中,直到遇到指定的分隔符delim为止。如果没有指定分隔符,则默认为换行符。读取的分隔符不包括在存储的字符串中。
int main()
{
	string line;
	char delim = ':';
	cout << "Enter a line with as delimiter :" << endl;
	getline(cin, line, delim);
	cout << "You entered:" << line << endl;
	return 0;
}

image-20230509113028819

getline(istream& is, string& str);

  • 🔥这个形式的函数从输入流is中读取一行文本,并将其存储在str字符串中,直到遇到换行符为止。读取的换行符不包括在存储的字符串中。

  • operator>> (重点)

image-20230509095046682

从流中提取字符串,从输入流中提取一个字符串,将该序列存储在str中,str被覆盖(之前的str值被替换)。

该函数重载运算符>>,使其行为与istream::operator>>中描述的一样,适用于c-string对象。

提取出的每个字符都会像调用push_back成员一样被添加到字符串中。

请注意,istream提取操作使用空格作为分隔符。因此,这个操作只会从流中提取可以认为是单词的内容。要提取整行文本,请参阅全局函数getline的字符串重载。

  • operator<< (重点)

image-20230509113440051

向流中插入字符串,将符合str的值的字符序列插入到os中。

  • relational operators (重点)

这个后面写模拟实现的时候,会详细讲解

image-20230509113755321

2.4String非常用接口说明

  • insert

在pos(或p)指定的字符之前插入额外的字符:

  • 🔥intsert不会将\0插入进去 的,string不推荐经常使用insert,能少用就少用

image-20230509114635482

int main()
{
	string s1("world");
	s1.insert(0, "hello");
	cout << s1 << endl;

	s1.insert(5, " ");
	cout << s1 << endl;
	return 0;
}
  • erase

从字符串中删除字符,删除字符串的一部分,减少其长度:

image-20230509115225380

  • 第一种:擦除字符串值中从字符位置pos开始并跨越len字符的部分(如果内容太短或len为string::npos,则擦除直到字符串末尾)。注意,默认实参会擦除字符串中的所有字符(类似于成员函数clear)。
  • 第二种:擦除指向p的字符。
  • 第三种:擦除[first,last)范围内的字符序列。
string s2("hello world");
	s2.erase(5, 1);
	cout << s2 << endl;

当删除的字符的个数超过了字符的个数会怎么样?

image-20230414151437990

  • replace

image-20230414151851659

int main()
{
	string s1("world");
	s1.insert(0, "hello");
	cout << s1 << endl;

	s1.insert(5, " ");
	cout << s1 << endl;
	return 0;
}

在这里插入图片描述

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

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

相关文章

Dockerfile部署java项目

一、dockerfile展示 将DockerFile 配置文件放到 maven项目目录内&#xff0c;和pom.xml同级。 # Download code FROM bitnami/git:2 AS git RUN mkdir -p /home/app/src RUN git -c http.sslVerifyfalse -C /home/app/src clone -b local https://github.com/test.git# # Bui…

2023年宜昌市中等职业学校技能大赛 “网络搭建与应用”竞赛题-1

2023年宜昌市中等职业学校技能大赛 “网络搭建与应用”竞赛题 一、竞赛内容分布 “网络搭建及应用”竞赛共分二个部分&#xff0c;其中&#xff1a; 第一部分&#xff1a;企业网络搭建部署项目&#xff0c;占总分的比例为50%&#xff1b; 第二部分&#xff1a;企业网络服…

打工人使用ChatGPT的一天!

众所周知&#xff0c;ChatGPT 自去年OpenAI 推出以来&#xff0c;这款 AI 聊天机器人可以说迅速成为了 AI 界的「当红炸子鸡」 作为一名资深的打工人&#x1f477;&#x1f3fb;‍♂️&#xff0c;我们应该怎样利用ChatGPT提高工作效率呢&#xff1f;今天给大家介绍下打工人使…

c++ cuda加速学习笔记

1. 环境配置 (1)显卡驱动下载官网&#xff0c;需要知道自己电脑的显卡类型 搜索链接&#xff1a;https://www.nvidia.com/Download/index.aspx?langzh-cn(2)怎么知道自己的的显卡类型 https://jingyan.baidu.com/article/2a13832888b2a7464a134fef.html 此电脑->管理->…

通过Modbus实现TTS语音全彩声光告警-博灵语音通知终端-网络语音报警灯

背景 目前PLC在工业领域应用广泛&#xff0c;在运行过程中可能会涉及到各种告警。 为了简单快速的实现语音声光告警&#xff0c;本文以大连英仕博科技出品的博灵语音通知终端为例&#xff0c;演示如何通过Modbus TCP协议实现声光告警推送。 播报效果演示 Modbus-博灵语音通知…

Google Play 政策更新重点回顾 (上) | 2023 年 4 月

Google Play 始终如一地为大家打造值得信赖的安全平台&#xff0c;支持大家走向成功。为了让您更及时更清晰地掌握 Google Play 最新政策&#xff0c;我们准备了两篇文章为您详细说明 2023 年 4 月的政策更新内容&#xff0c;以及深度解析。本文是第一篇内容&#xff0c;我们将…

日撸 Java 三百行day46

文章目录 说明day46 快速排序1.基本思路2. 代码 说明 闵老师的文章链接&#xff1a; 日撸 Java 三百行&#xff08;总述&#xff09;_minfanphd的博客-CSDN博客 自己也把手敲的代码放在了github上维护&#xff1a;https://github.com/fulisha-ok/sampledata day46 快速排序 …

计算机网络安全--期末

计算机网络安全绪论 计算机网络实体是什么 计算机网络中的关键设备&#xff0c;包括各类计算机、网络和通讯设备、存储数据的媒体、传输路线…等 典型的安全威胁有哪些 ★ ⋆ \bigstar\star ★⋆ 窃听(敏感信息被窃听)重传(被获取在传过来)伪造(伪造信息发送&#xff09;篡…

kubeadm 部署Kubernetes 集群一主多从集群并完成pod部署

目录 搭建环境准备三台虚拟机&#xff1a; 环境条件限制&#xff1a; 一&#xff0c;关闭交换分区 二&#xff0c;禁用selinux 三&#xff0c;防火墙关闭 四&#xff0c;docker安装 五&#xff0c;设置IPv4 流量传递到 iptables 六&#xff0c;配置k8s的yum源 七&#…

vue3学习三 computed

vue3中的computed 也被封装成了一个组合api , 所以我们使用的时候&#xff0c; 要 import {computed} from “vue” 和vue2样&#xff0c; computed 是有两种书写方式 简写方式和全写方式 <template><div> firstname:<input v-model"firstname" /&g…

【专题连载】基于5G+机器视觉的芯片检测解决方案

基于5G机器视觉的芯片检测解决方案 背景 机器视觉的价值体现在它能为工业生产带来产量的增加和产品质量的提升&#xff0c;并同时降低生产成本&#xff0c;推动了工业生产的快速发展&#xff0c;使工业生产企业真正从中受益。为了进一步压缩生产成本&#xff0c;工业控制的产…

信号与槽机制一

一、信号与槽 1、什么是信号与槽&#xff1f; 信号和槽是用于对象之间的通信&#xff0c;它是Qt的核心机制&#xff0c;在Qt编程中有着广泛的应用。如果想学好Qt&#xff0c;一定要充分掌握信号的槽的概念与使用。 2、信号和槽的代码实例 在Qt中&#xff0c;发送对象、发送的信…

FPGA上的视觉 SLAM

在FPGA开发板上实现基于立体视觉的 SLAM。 绪论 SLAM&#xff08;同步定位和地图绘制&#xff09;在自动驾驶、AGV 和无人机等各种应用中引起了人们的广泛关注。尽管目前有很多优秀的 SLAM 项目可以参考&#xff0c;但是他们的复杂性&#xff08;高性能&#xff09;及依赖性&am…

体验洞察 | 原来它才是最受欢迎的CX指标?

一直以来&#xff0c;企业都在试图追踪他们能否在整个客户旅程中始终如一地提供卓越的客户体验&#xff08;Customer Experience&#xff0c;简称“CX”&#xff09;&#xff0c;并通过多个CX指标&#xff0c;如NPS&#xff08;净推荐值&#xff09;、CSAT&#xff08;客户满意…

简单讲讲UE中的PlayerCameraManager

我们在平时开发中&#xff0c;少不了编写一些逻辑去控制相机&#xff0c;例如俯视角镜头与各个特写镜头的过渡切换&#xff0c;因此了解一些PlayerCameraManager是有必要的。 PlayerCameraManager是UE自带的相机管理组件&#xff0c;本身比较简单&#xff0c;一般需要自行扩展…

长短期记忆网络LSTM(long short-term memory)

递归神经网络 递归神经网络可以解决这个问题。它们是带有循环的神经网络&#xff0c;允许信息保留一段时间。 在上图中&#xff0c;A 代表神经网络主体, xt 是网络输入&#xff0c;ht是网络输出&#xff0c;循环结构允许信息从当前输出传递到下一次的网络输入。 一个递归神经网…

强烈推荐:一款中文AI问答、创作、绘画工具

前言 相信很多人已经听过ChatGPT这款人工智能机器人了&#xff0c;它能够根据用户输入的内容&#xff0c;自动生成智能回复。它使用自然语言处理技术&#xff0c;通过学习大量的文本资料&#xff0c;能够模拟人类的对话行为。它是由OpenAI开发的&#xff0c;一家非常伟大的人工…

6个月的测试,来面试居然要15K,我一问连5K都不值

2023年4月份我入职了深圳某家创业公司&#xff0c;刚入职还是很兴奋的&#xff0c;到公司一看我傻了&#xff0c;公司除了我一个自动化测试&#xff0c;公司的测试人员就只有2个开发3个前端1个测试还有2个UI&#xff0c;在粗略了解公司的业务后才发现是一个从零开始的项目&…

HNU-计算机系统-讨论课6

完整讲解视频&#xff1a;野生Gprof会梦见存储器山嘛&#xff1f;_哔哩哔哩_bilibili 别忘了一键三连哦 题 3&#xff1a; 在“存储器层次结构”一章的 6.6 节从存储器山的角度具象化 了存储器性能描述。 &#xff08; 1 &#xff09; 请阅读教材 6.6.1 内容&#xff08…

从 Elasticsearch 到 Apache Doris,10 倍性价比的新一代日志存储分析平台|新版本揭秘

日志数据的处理与分析是最典型的大数据分析场景之一&#xff0c;过去业内以 Elasticsearch 和 Grafana Loki 为代表的两类架构难以同时兼顾高吞吐实时写入、低成本海量存储、实时文本检索的需求。Apache Doris 借鉴了信息检索的核心技术&#xff0c;在存储引擎上实现了面向 AP …