STL——string剖析

news2024/12/13 1:35:23

STL——string剖析

文章目录

  • STL——string剖析
    • 1. C语言中的字符串
    • 2. 标准库中string的使用
      • 2.1 构造函数
      • 2.2 string的容量操作
        • resize和reserve
      • 2.3 string的增删查改
        • 插入操作
          • push_back:
          • insert:
        • 删除操作
          • pop_back:
          • erase
        • 查找操作
          • find
          • find_first_of
        • 修改操作
          • operator[]
          • at
          • front
          • back
      • 2.3 字符串其他操作
        • 字符串的拼接
          • operator+=(重要)
          • append
        • 字符串的替换
          • assign
          • replace
        • 字符串的比较
          • compare
        • 提取字串
          • substr
        • string转const char *
          • data
          • c_str(重要)
      • 2.4 重要的非成员函数
        • operator+(重要)
        • swap
        • 字符串IO
          • operator>>
          • operator<<
          • getline
        • relational operators
    • 3. string在不同编译器下的底层构造
      • 3.1 vs下string的结构
      • 3.2 g++下string的结构
    • 4. 写时拷贝
    • 5. 拓展阅读
    • 6. 两个常见面试题

1. C语言中的字符串

在C语言中,字符串是一段以’\0’结尾的字符集合,为了操作方便,C标准库定义了许多对字符串操作的库函数,但是这些库函数和字符串是分离的,和我们的"OOP"(面向对象编程)思想不太符合,而且底层空间需要用户自己维护,容易产生越界访问等错误。因此C++声明字符串实现有两个头文件,是C++对C语言头文件<string.h>的另一层封装,而C++真正重新定义实现string的标准是在头文件中。

2. 标准库中string的使用

string其实是模板类basic_string的一种实例化:

typedef basic_string<char> string;

2.1 构造函数

default(1)string(); string的默认构造函数,管理的字符串初始化为空串
copy (2)string (const string& str); string的拷贝构造函数,是深拷贝
substring (3)string (const string& str, size_t pos, size_t len = npos); 从str字符串中下标为pos的字符作为首字符,长度为len的子串构造新string,len有缺省参数npos,npos是一个size_t的常量(值非常大),用在长度中到表示字符串的结尾,也就是将pos - end的子串截取
from c-string (4)string (const char* s); 将C风格的字符串构造string
from sequence (5)string (const char* s, size_t n); 将C风格的字符串的前n个字符构造string
fill (6)string (size_t n, char c); 将n个字符c构造string
range (7)template <class InputIterator> string (InputIterator first, InputIterator last);使用迭代器模板构造string

2.2 string的容量操作

string管理字符串是通过动态开辟空间进行管理的,那么就需要合理的最利用空间,什么时候开辟空间,什么时候缩小空间就很重要了。因此也就有了一系列为了管理字符串内存空间的变量和函数:

成员解释类型
capacity成员变量,表示string的容量,存放的有效字符个数的上限,capacity >= sizesize_t
size成员变量,表示有效字符个数size_t
length成员变量,同样表示有效字符个数size_t
max_size成员函数,表示string最多存储多少有效的字符个数,返回值是一个很大的数,一般比容量大得大得多size_t ()
empty成员函数,表示字符串是否为空串bool ()
clear成员函数,将字符串清空,不会释放空间,不会改变容量,但会改变有效字符个数void ()
resize成员函数,用来将字符串的有效个数改成nvoid (size_t n, char c)
void (size_t n)
reserve成员函数,用来更改字符串的容量void (size_t n )
resize和reserve

resize:

void resize(size_t n)
void resize(size_t n, char c)

resize根据n分为四种情况:

  1. 当n < size时:

    字符串会截断,有效长度减少至n;

  2. 当n == size时:

    什么都不做;

  3. 当size < n <= capacity时:

    将把字符串的有效长度增长到n,如果给出了c,则添加的字符全部用c填充,没给出则默认用’\0’;

  4. 当n > capacity时:

    会先根据string的扩容规则(reserve函数)进行扩容,然后再将字符串的size填充至n。

resize的作用一般是来填充字符串和截断字符串的,但是当填充的长度超过容量时,就要使用reserve函数进行扩容了。

reserve:

void reserve(int n)

reserve根据n也会分两种情况:

  1. 当n <= capacity时:
    什么都不会做;

  2. 而当n > capacity时:

    容量进行扩容至n或者大于n,具体实现根据对应的编译器下的标准库的扩容规则(vs的规则一般为扩1.5倍,g++一般为扩2倍)

2.3 string的增删查改

插入操作

字符串的插入操作一般有两个:

  1. push_back(尾插),只能用来在尾部插入单个字符,效率高;
  2. insert,可以在任意位置插入字符或者字符串。
push_back:
void push_back (char c);

尾插函数,并且只允许插入一个字符,但是尾插效率高,时间复杂度为O(1)。

insert:
string& insert (size_t pos, const string& str);
string& insert (size_t pos, const string& str, size_t subpos, size_t sublen);
string& insert (size_t pos, const char* s);
string& insert (size_t pos, const char* s, size_t n);	
string& insert (size_t pos,   size_t n, char c);
iterator insert (const_iterator p, size_t n, char c);
iterator insert (const_iterator p, char c);

insert实现的重载比较多,允许各种形式的参数,但是参数的意义比较固定。

参数解析:

  • pos:插入的下标,插入时是将原下标和其右边的字符串右移,再将要插入的内容填充;
  • str:要插入的string对象管理的字符串;
  • subpos:表示我们要插入str的子串,该子串的起始下标为subpos;
  • sublen:表示str子串的长度,和subpos配合,表示要插入str中的其实位置下标为subpos,长度为sublen的子串;
  • s:要插入的字符串;
  • n:要插入的字符串s的前n个字符;
  • c:要插入的字符,如果和n配合,表示要插入n个字符;
  • p:指向要插入位置上字符的迭代器,和pos差别不大,通常我们想要表示第i个位置字符的迭代器可以用string.begin() + i。
删除操作
pop_back:
void pop_back ();

尾删函数,删除字符串结尾的一个字符,将有效字符减小一个,时间复杂度也是O(1)。
注意:如果调用时字符串是空串,是一个未定义行为,因此调用前检查字符串是否为空串很重要。

erase
string& erase (size_t pos = 0, size_t len = npos);
iterator erase (iterator p);
iterator erase (iterator first, iterator last);

参数解析:

  • pos:要删除的字符串的起始下标;
  • len:要删除的字符串的长度;
  • p:删除字符串的单个字符的迭代器;
  • first:要删除的字符串的起始位置字符的迭代器;
  • last:要删除的字符串的结尾位置字符的迭代器。

返回值:

string&:删除后的字符串对象的*this;

iterator:删除的迭代器或者迭代器区间的下一个元素的迭代器。

注意:迭代器的使用都是左闭右开,也就是说,last位置的字符不会被删除,而是到last结束。

查找操作

字符串的查找操作主要依赖find家族,这些函数属于算法一类,并不是string的成员函数,并且对很多容器都适用。

这里只举例常用的find和find_first_of的操作:

find
size_t find (const string& str, size_t pos = 0) const;
size_t find (const char* s, size_t pos = 0) const;
size_t find (const char* s, size_t pos, size_t n) const;	
size_t find (char c, size_t pos = 0) const;

参数说明:

  • ch: 要查找的字符;
  • str: 要查找的子字符串;
  • s: 要查找的 C 风格字符串;
  • pos: 开始查找的位置,默认为 0,表示从字符串的开头开始查找;
  • n: 要查找的字符数组的长度(仅在使用字符数组时适用)。

返回值:
返回值是 size_t 类型,表示找到的字符或子字符串的索引位置。如果未找到,返回 std::string::npos,作为返回值,这是一个常量,表示无效位置。

这是一个从左向右查找的函数,用于查找第一个匹配的字符串的下标。

find_first_of
size_t find_first_of (const string& str, size_t pos = 0) const noexcept;
size_t find_first_of (const char* s, size_t pos = 0) const;
size_t find_first_of (const char* s, size_t pos, size_t n) const;	
size_t find_first_of (char c, size_t pos = 0) const noexcept;

功能: 查找在给定的 std::string 中的任意字符首次出现的位置。
参数解析:

  • str: 包含要查找的字符集合的 std::string;
  • pos: 开始查找的位置,默认为 0。

返回值:

返回找到的字符的索引位置,如果未找到则返回 std::string::npos。

其它的find家族函数:

  • rfind:和find方向相反,这是一个从右往左查找的函数,用于反向查找一个匹配的字符串的下标;
  • find_last_of:查找在给定的字符串或字符任意字符最后一次出现的位置;
  • find_first_not_of:查找第一个不在给定的字符串或字符的任意字符的出现的位置;
  • find_last_not_of:查找最后一次不在给定的字符串或字符的任意字符的出现的位置。
修改操作

string对指定元素进行修改,需要获取到字符位置的地址或者引用,而string通过重载运算符operator[]实现了获取指定下标元素的引用,从而让程序员直接可以修改。

operator[]
char& operator[](size_t pos);
const char& operator[](size_t pos) const; 

string类型可以通过下标运算符的重载获取对应下标的字符的引用,也就是说可以直接对字符串的指定下标的字符进行修改,注意还同样重载了const版本的operator[]。

同样的,string还实现了at成员函数,作用和operator[]一样。

at
char& at (size_t pos);
const char& at (size_t pos) const;

at和operator[]的效果一样,都是获取指定下标的字符的引用,可以直接对字符串进行修改。

返回值同样是char&的还有front和back:

front
char& front();
const char& front() const;

取出首字符的引用。

back
char& back();
const char& back() const;

取出最后一个字符的引用。

2.3 字符串其他操作

字符串的拼接
operator+=(重要)
string& operator+= (const string& str);
string& operator+= (const char* s);
string& operator+= (char c);

string类型可以通过+=实现直接在原来字符串的基础上增加新字符,重载有三个版本,分别可以和string类型、字符串、字符进行+=,并且返回的是+=完后的原string类型(*this)的引用。

append
string& append (const string& str);
string& append (const string& str, size_t subpos, size_t sublen);	
string& append (const char* s);
string& append (const char* s, size_t n);
string& append (size_t n, char c);

参数的意义和insert一样,但是它不需要像insert一样给出插入位置字符的下标或者迭代器,因为它固定插入位置是在最后一个字符后,返回值均为调用该函数的string对象的*this引用。

字符串的替换
assign
string& assign (const string& str);
string& assign (const string& str, size_t subpos, size_t sublen);
string& assign (const char* s);
string& assign (const char* s, size_t n);
string& assign (size_t n, char c);

参数解析:

  • str:将原string对象的字符串完全替换成str的字符串;
  • subpos:表示将原string对象的字符串完全替换成str的子串,该子串的起始位置为subpos;
  • sublen:该子串的长度;
  • s:将原字符串替换成指定的C风格字符串,\0也会赋值过去,但是不会算进有效字符;
  • n:和c一起配合,表示要替换成n个c字符;
  • c:要替换的字符。

返回值:

*this。

replace
string& replace (size_t pos,  size_t len,  const string& str);
string& replace (iterator i1, iterator i2, const string& str);
string& replace (size_t pos,  size_t len,  const string& str, size_t subpos, size_t sublen);
string& replace (size_t pos,  size_t len,  const char* s);
string& replace (iterator i1, iterator i2, const char* s);
string& replace (size_t pos,  size_t len,  const char* s, size_t n);
string& replace (iterator i1, iterator i2, const char* s, size_t n);	
string& replace (size_t pos,  size_t len,  size_t n, char c);
string& replace (iterator i1, iterator i2, size_t n, char c);

和assign不同,assign是把原字符串全部替换,而replace可以只替换一部分子串,但是一定要注意pos和len是否合法,编译器不会判断是否越界,一旦越界,访问到了释放的空间,严重会造成程序终止。
这里参数就不展开讲了,了解了前面的函数,其实会对字符串参数有个大概的了解,如果要指定位置,通常用下标和迭代器,指定字符串长度有len,指定字符有c,指定字符的个数有n,指定C风格字符串有s,指定string类型有str,这里的i1、i2和前面的first和last差不多。

字符串的比较

字符串之间的比较,其实就是将对应下标位置上的字符分别对应比较,由于char类型的字符实际就是一个整形(由ASCLL码表示),因此根据ASCLL码值的大小进行比较,并且顺序从左往右,直到一方字符串字符的ASCLL码值更小或者长度更短。

compare
int compare (const string& str) const noexcept;
int compare (size_t pos, size_t len, const string& str) const;
int compare (size_t pos, size_t len, const string& str, size_t subpos, size_t sublen) const;
int compare (const char* s) const;
int compare (size_t pos, size_t len, const char* s) const;
int compare (size_t pos, size_t len, const char* s, size_t n) const;

参数解析:

  • const std::string& str:要比较的另一个 std::string 对象。
  • size_t pos1:当前字符串中开始比较的起始位置。
  • size_t len1:当前字符串中要比较的字符数。
  • const char* s:要比较的 C 风格字符串。
  • size_t n:要比较的 C 风格字符串的长度。

返回值:
一个int类型,表示比较的结果。

比较规则:(我们将原string对象的字符串的字符作为左,要比较的对象的字符作为右)

  1. 当左字符的ASCLL码值 > 右字符的ASCLL码值,返回一个大于0的数(通常用1表示)
  2. 当左字符的ASCLL码值 < 右字符的ASCLL码值,返回一个小于0的数(通常用-1表示)
  3. 当左字符的ASCLL码值 == 右字符的ASCLL码值,继续下一个下标的字符的比较
  4. 如果左右字符串一模一样,也就会一直比较直到下标走到了字符串结尾,那么就会返回0
  5. 当有一方的下标先到了字符串结尾,也认为是小于对方(这里巧妙的点在于,如果我们对string对象的字符串结尾都处理以\0结尾,\0的ASCLL码值就为0,跟任何字符比较都是更小,也就省去了判断长度)
提取字串
substr
string substr (size_t pos = 0, size_t len = npos) const;

提取pos位置为起始位置,len为长度的子串,两个参数都有缺省值,如果都没给,表示提取string对象自身的字符串
返回值不是一个引用而是一个拷贝。
注意:由于 npos 的值是 size_t 的最大值,它可以被视为一个无效的长度值。在某些情况下,使用 npos 作为长度可以表示一个超出有效范围的长度。也就是说当npos作为字符串长度时,由于字符串不能提取超出有效长度之外的字符,那么只会把从指定位置到结尾的所有字符选中,所以npos常用来选中指定位置到结尾的子串。

string转const char *
data
const char* data ();
c_str(重要)
const char* c_str ();

两者没有明显不同,返回的指针都指向原string对象的字符串在内存中的起始地址,唯一的不同是在C++11以前data返回的字符串并不一定以’\0’结尾,而c_str始终返回一个以\0结尾的字符串,因此c_str更常用。

2.4 重要的非成员函数

operator+(重要)
string operator+ (const string& lhs, const string& rhs);
string operator+ (const string& lhs, const char* rhs);
string operator+ (const char* lhs, const string& rhs);
string operator+ (const string& lhs, char rhs);
string operator+ (char lhs, const string& rhs);

operator+是string类外重载的一个运算符,它允许string类型可以和多种类型的变量运算:

  • string + string
  • string + const char*
  • string + char
  • const char* + string
  • char + string

注意:string和其他变量运算是不会修改自身的值的,而是会生成一个新的拷贝,因此尽量少用,因为是传值返回(一旦字符串长度比较长,一个字符就是一个字节),会导致深拷贝的效率低。

swap
void swap (string& x, string& y);

令x和y的字符串交换。

字符串IO
operator>>
std::istream& operator>>(std::istream& is, std::string &str);

流插入运算符重载,正是因为重载了>>我们才能实现std::cin >> str;从终端命令行给str赋值(is实际上可以是任意的输入流),但是is遇到空格就会结束,因此不能把带有空格的字符串赋值给str。
返回值:

是is的引用,这样可以实现 is >> str >> str1 >> str2;多个字符串的输入。

operator<<
ostream& operator<< (ostream& os, const string& str);

流提取运算符重载,可以将str输出到指定的输出流当中。

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

由于is不能实现带有空格字符串的赋值,因此getline实现了
参数解析:

  • is:读取流对象的引用;
  • str:读取的字符串赋值的字符串;
  • delim:分隔符,默认为\0,当读到delim时停止,不会把delim读进str。
relational operators

除了[]、+=、+外,标准库还重载了一些关于string的操作符函数:

bool operator== (const string& lhs, const string& rhs);
bool operator!= (const string& lhs, const string& rhs);
bool operator<  (const string& lhs, const string& rhs);
bool operator<= (const string& lhs, const string& rhs);
bool operator>  (const string& lhs, const string& rhs);
bool operator>= (const string& lhs, const string& rhs);

这是一些特定的比较运算符的重载,字符串的比较规则和compare一样。

3. string在不同编译器下的底层构造

注意:下述结构是在32位平台下进行验证,32位平台下指针占4个字节。

3.1 vs下string的结构

string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来定义string中字 符串的存储空间:

  • 当字符串长度小于16时,使用内部固定的字符数组来存放 ;
  • 当字符串长度大于等于16时,从堆上开辟空间。
union _Bxty
{ // storage for small buffer or pointer to larger one
 value_type _Buf[_BUF_SIZE];
 pointer _Ptr;
 char _Alias[_BUF_SIZE]; // to permit aliasing
} _Bx;

这种设计也是有一定道理的,大多数情况下字符串的长度都小于16,那string对象创建好之后,内部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高;

其次:还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量 ;

最后:还有一个指针做一些其他事情。 故总共占16+4+4+4=28个字节。

在这里插入图片描述

3.2 g++下string的结构

g++下,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指 针将来指向一块堆空间,内部包含了如下字段:

  • 空间总大小
  • 字符串有效长度
  • 引用计数
struct _Rep_base
{
 size_type _M_length;
 size_type _M_capacity;
 _Atomic_word _M_refcount;
};
  • 指向堆空间的指针,用来存储字符串。

4. 写时拷贝

写时拷贝(COW) 是一种优化技术,允许多个对象共享同一块内存,直到其中一个对象需要修改数据时,才会创建该数据的副本。这种方式可以节省内存和提高性能,尤其是在处理大量相同数据的情况下。

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。

引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给 计数增加1,当某个对象被销毁时,先给该计数减1,然后再检查是否需要释放资源,如果计数为1,说明该 对象时资源的最后一个使用者,将该资源释放;否则就不能释放,因为还有其他对象在使用该资源。

写时拷贝

写时拷贝在读取时的缺陷

5. 拓展阅读

面试时string的一种正确写法
STL中的string类怎么了

6. 两个常见面试题

LCR 192. 把字符串转换成整数 (atoi) - 力扣(LeetCode)

字符串相加

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

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

相关文章

Ubuntu24.04配置STMTrack

项目地址&#xff1a;https://github.com/fzh0917/STMTrack 一、安装 CUDA 参考链接&#xff1a; Ubuntu24.04配置DINO-Tracker Ubuntu多CUDA版本安装及切换 由于之前在其他项目中已经安装了 CUDA12.1&#xff0c;这次需要安装另一个版本。 1. 查看安装版本 按照 requireme…

Android显示系统(08)- OpenGL ES - 图片拉伸

Android显示系统&#xff08;02&#xff09;- OpenGL ES - 概述 Android显示系统&#xff08;03&#xff09;- OpenGL ES - GLSurfaceView的使用 Android显示系统&#xff08;04&#xff09;- OpenGL ES - Shader绘制三角形 Android显示系统&#xff08;05&#xff09;- OpenGL…

【实现多网卡电脑的网络连接共享】

电脑A配备有两张网卡&#xff0c;分别命名为eth0和eth1&#xff08;对于拥有超过两张网卡的情况&#xff0c;解决方案相似&#xff09;。其中&#xff0c;eth0网卡能够连接到Internet&#xff0c;而eth1网卡则通过网线直接与另一台电脑B相连&#xff08;在实际应用中&#xff0…

聊聊在应用层面实现内网穿透功能是否可行

前言 最近接手了供方开发的网关项目&#xff0c;交接文档里面有个内网穿透的功能&#xff0c;一下子就吸引的我的目光。实现这个内网穿透的背景是业务部门有些业务是部署在公网&#xff0c;这些公网的业务想访问内网的业务&#xff0c;但因为公网和内网没打通&#xff0c;导致…

头歌 计算机操作系统 Linux之线程同步二

第1关&#xff1a;信号量 任务描述 在上一个实训中&#xff0c;我们学习了使用互斥锁来实现线程的同步&#xff0c;Linux系统中还提供了另一个类似互斥锁的线程不同操作&#xff0c;那就是信号量。 本关任务&#xff1a;学会使用信号量来实现线程间的同步与互斥。 相关知识 …

基于MinIO打造高可靠分布式“本地”文件系统

MinIO是一款高性能的对象存储服务&#xff0c;而S3协议是由亚马逊Web服务&#xff08;AWS&#xff09;制定的一种标准协议&#xff0c;用于云存储服务之间的数据交换。MinIO与S3协议的关系在于&#xff0c;MinIO实现了S3协议的接口&#xff0c;这意味着用户可以使用与AWS S3相同…

【MIT-OS6.S081作业1.3】Lab1-utilities primes

本文记录MIT-OS6.S081 Lab1 utilities 的primes函数的实现过程 文章目录 1. 作业要求primes (moderate)/(hard) 2. 实现过程2.1 代码实现 1. 作业要求 primes (moderate)/(hard) Write a concurrent version of prime sieve using pipes. This idea is due to Doug McIlroy, in…

Js如和返回数组中的指定列

一、需求 日常工作中需要返回数组中的指定列&#xff0c;例如Echarts 和 下拉框 选择 id&#xff0c;value 类似这种都需要在数组中提取指定列元素。 二、代码示例 const products [{ name: "商品1", price: 100, inventory: 50 },{ name: "商品2", pri…

C++的一些经典算法

以下是C的一些经典算法&#xff1a; 一、排序算法 冒泡排序&#xff08;Bubble Sort&#xff09; 原理&#xff1a; 它重复地走访过要排序的数列&#xff0c;一次比较两个元素&#xff0c;如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换…

35.1 thanos项目介绍和二进制部署

本节重点介绍 : 核心优点 无需维护存储&#xff0c;存储高可用&#xff1a; 利用廉价的公有云对象存储&#xff0c;高可用长时间存储&#xff0c;数据降采样&#xff1a;利用Compactor降采样完全适配原生prometheus查询接口&#xff1a;Query实现多级数据缓存配置 二进制部署 …

【PlantUML系列】状态图(六)

一、状态图的组成部分 状态&#xff1a;对象在其生命周期内可能处于的条件或情形&#xff0c;使用 state "State Name" as Statename 表示。初始状态&#xff1a;表示对象生命周期的开始&#xff0c;使用 [*] 表示。最终状态&#xff1a;表示对象生命周期的结束&…

Android 15(V)新功能适配,雕琢移动细节之美

Android 15&#xff0c;内部代号为Vanilla Ice Cream&#xff0c;是Android移动操作系统的最新主要版本&#xff0c;于2024年2月16日在开发者预览版1中发布。Android 15源代码于 2024年9月4日发布。Android 15稳定版于2024年10月15日发布。 以下是针对 Android 15&#xff08;…

【零成本抽象】基本概念与在C++中的实现

零成本抽象概念是由 Bjarne Stroustrup 提出的,他在 1994 年的著作中就有相关设想,2016 年其在 C++ 大会登台演讲时,明确阐述了 C++ 中的 “零成本抽象” 这一理念。 一、零成本抽象概念 Bjarne Stroustrup提出的零成本抽象概念,是指在编程中使用高级抽象机制时,不会产生…

android编译assets集成某文件太大更新导致git仓库变大

不知道大家有没有类似的困扰&#xff0c;你的工程assets文件过大&#xff0c;我曾经在某度车机地图团队工作过一段时间时候&#xff0c;每次发包会集成一个上百MB的文件。工作一段时间你的git仓库将会增加特别多。最后&#xff0c;你会发现你如果重新git clone这个仓库会非常大…

F5-TTS文本语音合成模型的使用和接口封装

F5-TTS文本语音生成模型 1. F5-TTS的简介 2024年10月8日&#xff0c;上海交通大学团队发布&#xff0c;F5-TTS (A Fairytaler that Fakes Fluent and Faithful Speech with Flow Matching) 是一款基于扩散Transformer和ConvNeXt V2的文本转语音 (TTS) 模型。F5-TTS旨在生成流…

克隆选择算法复现

克隆选择算法复现 基于克隆选择算法求解0 - 1背包问题的代码复现文档一、背景和意义&#xff08;一&#xff09;背景&#xff08;二&#xff09;意义 二、算法原理&#xff08;一&#xff09;克隆选择算法基础&#xff08;二&#xff09;受体编辑机制 三、算法流程&#xff08;…

Scala的隐式对象

Scala中&#xff0c;隐式对象&#xff08;implicit object&#xff09;是一种特殊的对象&#xff0c;它可以使得其成员&#xff08;如方法和值&#xff09;在特定的上下文中自动可用&#xff0c;而无需显式地传递它们。隐式对象通常与隐式参数和隐式转换一起使用&#xff0c;以…

观察者模式的理解和实践

引言 在软件开发中&#xff0c;设计模式是开发者们为了解决常见的设计问题而总结出来的一系列最佳实践。观察者模式&#xff08;Observer Pattern&#xff09;是其中一种非常经典且使用率极高的设计模式。它主要用于定义对象之间的一对多关系&#xff0c;使得当一个对象的状态发…

windows下Qt5自动编译配置QtMqtt环境(11)

文章目录 [toc]1、概述2、准备1.1 下载源码1.2 配置环境1.3 解释原理 3、编译4、验证5、参考6、视频 更多精彩内容&#x1f449;内容导航 &#x1f448;&#x1f449;Qt网络编程 &#x1f448; 1、概述 Qt默认是不包含mqtt库的&#xff0c;如果需要使用到mqtt库就只能自己编译配…

【6】数据分析检测(DataFrame 1)

学习目标3 昨天&#xff0c;我们学习了Series。 而Pandas的另一种数据类型&#xff1a;DataFrame&#xff0c;在许多特性上和Series有相似之处。 今天&#xff0c;我们将学习DataFrame的相关知识&#xff1a; 1. DataFrame的概念 2. 构造一个DataFrame 3. DataFrame的常用…