功能 :使用C-string构造string类对象 。在非空字符串中,从s指向位置拷贝一份字符串。
2.3 string(size_t,char c)
int main ( )
{
string str1 ( 5 , 'x' ) ;
cout << str1 << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :string类对象初始化n个字符c。从C-string的n个连续字符拷贝填充string类对象。
2.4 string(const string& s)
int main ( )
{
string str1 ( "hello world" ) ;
string str2 ( str1) ;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
2.5 string(const string& str,size_t pos,size_t len = npos)
int main ( )
{
string str1 ( "helloo world" ) ;
string str2 ( str1, 5 , 6 ) ;
cout << str2 << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :从str中pos指向位置先后拷贝len长度字符 。出现两种结果:拷贝到str最后一个字符或没有达到最后一个字符完成拷贝。
说明:第三个参数len类型为size_t,而缺省值npos == -1导致了npos为最大值128(涉及到编码那块)。对于当没有明确len数值,默认是从pos位置拷贝字符串到最后一个字符。
三、string类对象的容量操作
class="table-box">函数名称 功能说明 size(重点) 返回字符串有效字符长度 length 返回字符串有效字符长度 capacity 返回空间总大小 empty (重点) 检测字符串释放为空串,是返回true,否则返回false clear (重点) 清空有效字符 reserve (重点) 为字符串预留空间 resize (重点) 将有效字符的个数该成n个,多出的空间用字符c填充
3.1 Size与length
int main ( )
{
string str1 ( "hello world" ) ;
cout << str1. size ( ) << endl;
cout << str1. length ( ) << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :返回字符串有效字符长度。
3.1.1 关于size与length相关问题
至于出现两个功能类似接口的原因 :
由于当时string只考虑字符串,同时使用length表示字符串长度是最合理的。但是这样没有考虑到其他类型,导致具有局限性,在树形结构等数据结构情况中不太适合length表示元素大小,STL添加size表示元素大小。length合理,size统一更规范。
为什么不删除length,只保留size呢?或者在string容器中只存在length表示大小呢?
在语言中库,一般遵守向前兼容,只错不能改。如果修改会导致之前代码就编译失败,对此不能删除length。其他容器都有size,就你string容器没有,是不是有点不太合适呀。
3.2 capacity
int main()
{
string str1("hello world");
cout << str1.size() << endl;
cout << str1.capacity() << endl;
return 0;
}
输出结果:11 15
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :返回空间总大小,一般情况下capacity返回大小中不包含’\0’
3.2.1 capacity返回值比size大
在C++中,std::string底层属于动态数组,数组大小是不固定,根据实际需要进行调正。由于经常性出现频繁插入字符的清空,只存在size情况下,会导致频繁地向系统申请空间,性能降低。
capacity可以有效地解决这问题,直接申请大于size空间大小,避免在每次追加字符中重新分配内存,直接使用capacity空间,减少向系统申请内存次数,提高性能。
3.2.2 capacity扩容机制
在C++中,std::string类中向字符串添加字符。如果出现容量不足去容纳新字符,会自动扩容(不需要手动扩容)。扩容的逻辑通常按照某种策略增加容量,具体实现会跟编译器和指标因子的不同有所差异 。虽然string扩容机制没有明确的规定细节,但是不会影响功能。
VS :扩容机制是第一次扩容到原来空间的两倍左右,之后则扩容当前空间的1.5倍GCC :扩容机制是以当前空间的两倍
3.3 empty
int main ( )
{
string str1;
if ( str1. empty ( ) )
cout << "为空" << endl;
else
cout << "非空" << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :检测字符串是否释放为空,是空返回true,否则返回false
3.4 clear
int main ( )
{
string str1 ( "hello world" ) ;
cout << str1. size ( ) << endl;
cout << str1. capacity ( ) << endl;
str1. clear ( ) ;
cout << str1. size ( ) << endl;
cout << str1. capacity ( ) << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能:清空string有效字符资源,不改变底层空间大小 。影响有效元素size,不会影响空间容量大小capacity
3.5 shrink_to_fit
int main ( )
{
string str ( "hello world" ) ;
cout << str. size ( ) << endl;
cout << str. capacity ( ) << endl;
cout << endl;
str. resize ( 100 ) ;
cout << str. size ( ) << endl;
cout << str. capacity ( ) << endl;
cout << endl;
str. shrink_to_fit ( ) ;
cout << str. size ( ) << endl;
cout << str. capacity ( ) << endl;
cout << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
class="hide-preCode-box">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
功能 :向系统请求字符串缩容到适合大小,但是该函数对于字符串的长度和内容是没有影响的
如果使用shrink_to_fit后,容量没有发生改变,可能字符串对象可能已经使用内存管理策略去避免频繁的内存分配和释放。
3.6 reserve(重要)
int main ( )
{
string str1;
cout << str1. capacity ( ) << endl;
str1. reserve ( 100 ) ;
cout << str1. capacity ( ) << endl;
string str2 ( 10 , 'x' ) ;
cout << str2. capacity ( ) << endl;
str2. reserve ( ) ;
cout << str2. capacity ( ) << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :向系统申请预留空间,属于手动扩容
3.6.1 关于reserve与扩容问题
编译器会根据capacity容量自动扩容,那么为什么还需要reserve实现手段扩容呢?
理由 :扩容是需要付出代价的,如果是异地扩容,付出代价更大,需要进行空间开辟和数据拷贝。如果事先知道所需要的空间大小,使用reverse开辟足够使用的空间,减少频繁对内存的重分配,就算后期出现空间不足,也有自动扩容的机制,不需要担心大小是固定的。虽然自动扩容可以解决容量不足的情况,但是手段扩容可以减少频繁自动扩容的代价,属于一种优化手段。
reverse要求100个字节空间,但却开辟了111个字节空间呢?
理由 :在不同编译器下机制是不同的,但是确保了至少满足所需空间。有些编译器开辟多个空间,是对reserve开辟的空间进行了二次开辟,可以灵活调用内存空间分配,在后继需要小空间,避免扩容。
reserve参数部分小于当前空间大小,提出申请空间请求,但是空间大小并没有发生改变
理由 :reserve进行扩容必须参数部分比当前空间大,才会改变string的底层空间总大小,否则就是无效扩容。
3.7 resize(重要)
功能 :改变字符串的实际长度
3.7.1 resize改变字符串的实际长度有三种情况
第一种 :字符串变短(n>size)
int main ( )
{
string str1 ( "hello world" ) ;
cout << str1. size ( ) << endl;
cout << str1. capacity ( ) << endl;
str1. resize ( 2 ) ;
cout << str1 << endl;
cout << str1. size ( ) << endl;
cout << str1. capacity ( ) << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
第二种 :字符串在容量内变长(capacity>=n>size)
int main ( )
{
string str1 ( "hello world" ) ;
cout << str1. size ( ) << endl;
cout << str1. capacity ( ) << endl;
str1. resize ( 13 ) ;
cout << str1 << endl;
cout << str1. size ( ) << endl;
cout << str1. capacity ( ) << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
如果需要保留字符串前几个字符(不包括‘\0’),可以使用这个接口。
第三种 :字符串修改长度超出容量(n>capcity)
int main ( )
{
string str1 ( "hello world" ) ;
cout << str1. size ( ) << endl;
cout << str1. capacity ( ) << endl;
str1. resize ( 50 ) ;
cout << str1 << endl;
cout << str1. size ( ) << endl;
cout << str1. capacity ( ) << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
当resize修改长度超过capacity,capacity会进行自动扩容。至于最后capacity的值为什么不是50,在reserve中解释了不同编译器扩容机制是不同的。
resize有两个函数重载 :resize(size_t n)与resize(size_t n,char c),功能都是将字符串中有效字符个数改变到n个。
不同点 :当字符个数增多时
resize(n):用’\0’来填充都出的元素空间 resize(size_t n,char c):用字符c来填充多出的元素空间
虽然resize的功能很丰富,但是reserve比较多使用,可以提前开好空间,避免频繁扩容,提高了性能。
四、string类对象的访问
关于string类对象的访问,关键掌握operator[]就行 。剩下三个不如operator[]好用,其中front、back是为了规范性才实现的。
4.1 operator[]
int main()
{
string str1("hello world");
for (int i=0;i
class="hide-preCode-box">1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
五、string类对象的遍历操作
class="table-box">函数名称 功能说明 operator[] (重 点) 返回pos位置的字符,const string类对象调用 begin+ end begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器 rbegin + rend begin获取一个字符的迭代器 + end获取最后一个字符下一个位置的迭 代器 范围for C++11支持更简洁的范围for的新遍历方式
string类对象三种遍历方式 :
for+[] 范围for(本质还是迭代器) 迭代器(begin(),end())
这个三种遍历方式不仅可以遍历string对象,还能遍历修改string中的字符
注意:在string遍历时使用最多的是for+下标方括号[]或者范围for (C++11后才支持)。begin()+end()大多数使用在需要使用STL提供的算法操作string时,比如:采用reverse逆置string。
第一种 :for+下标方括号[]
int main ( )
{
string str1 ( "hello world" ) ;
int sz = str1. size ( ) ;
for ( int i = 0 ; i < sz; i++ )
{
第二种 :范围for
int main ( )
{
string str1 ( "hello world" ) ;
int sz = str1. size ( ) ;
for ( auto ch : str1)
{
cout << ch << endl;
}
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
接下来单独介绍下迭代器
六、迭代器(简单介绍)
6.1 迭代器概念
迭代器(Iterator)是一种用于遍历容器(如列表、字典、集合等)元素的对象。它提供了一种统一的访问容器内部元素的方式,而不必暴露容器的具体实现细节 。迭代器通常用于循环结构中,让程序员能够逐个访问容器中的元素。
int main ( )
{
string str1 ( "hello world" ) ;
string:: iterator it = str1. begin ( ) ;
while ( it != str1. end ( ) )
{
cout << * it << endl;
it++ ;
}
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
虽然推荐使用上面两种方式,但是迭代器才是主流 。对于链表、树等数据结构,迭代器不在乎底层实现,是通用的遍历容器。迭代器是一种像指针的东西,他可以是指针也可以不是指针,具体还是看不同编译器的底层实现,迭代器有两种类型分别 :可读可修改,可读不可修改
在string中定义迭代器:
string::iterator it = str1.begin();
string::iterator it = str1.end();
简单说明 :
begin()返回指向第一个位置的迭代器或指针,可以用于访问第一个位置元素,而end()返回指向最后一个位置之后的迭代器,它指向的是标记字符串的结尾。
可以使用容器类型的迭代器类型来声明变量:std::vector
容器,begin()和end()
返回的是str::vector::iterator
类型的迭代器,可以将其存储相应的变量中。
总之,存储迭代器的变量类型应该与容器的迭代器类型相匹配 ,以确保类型的一致性,避免编译器报错或者意外行为
6.2 反向迭代器(reverse_iterator)
反向迭代器定义:string::reverse_iterator
int main ( )
{
string str1 ( "hello world" ) ;
string:: reverse_iterator rit = str1. rbegin ( ) ;
while ( rit != str1. rend ( ) )
{
cout << * rit << "" ;
++ rit;
}
cout << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
说明 :rbegin()返回逆向迭代器位置,由于本来就是倒置的,++就是向前遍历。实际上很少使用场景,正向迭代器也可以满足倒着遍历的需求。
七、Modifiers(string类对象的修改操作)
class="table-box">函数名称 功能说明 push_back 在字符串后尾插字符c append 在字符串后追加一个字符串 operator+= (重点) 在字符串后追加字符串str c_str(重点) 返回C格式字符串 find + npos(重点) 从字符串pos位置开始往后找字符c,返回该字符在字符串中的位置 rfind 从字符串pos位置开始往前找字符c,返回该字符在字符串中的位置 substr 在str中从pos位置开始,截取n个字符,然后将其返回
对string操作时,如果能够大概预估到放多少字符,可以先通过reserve把空间预留好,减少扩容次数,提高性能
7.1 push_back
int main ( )
{
string str1;
for ( int i = 0 ; i < 10 ; i++ )
{
str1. push_back ( 'c' ) ;
}
cout << str1 << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :将一个字符尾插到字符串中
疑问 :push_back也不常用,既然支持一个字符尾插,为什么不顺便支持字符串。需要实现个支持字符串的接口,两个接口放在一起显得冗余
7.2 append
int main ( )
{
string str1;
str1. append ( "hello world" ) ;
cout << str1 << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :在字符串后追加一个字符串
对于append有很多个函数重载,这里只需要记住经常使用的就行了,其他了解下即可,但是无论是push_back,还是append,我们都不喜欢使用的,比较喜欢使用operator+=
7.3 operator+=(重要)
int main ( )
{
string str1, str2;
str1 += 'c' ;
cout << str1 << endl;
str2 += "hello world" ;
cout << str2 << endl;
str2 += str1;
cout << str2 << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
注意 :虽然str1.push_back('c')、str1.append(1,'c')、str1+='c'
三种的实现逻辑差不多,但是一般情况string类使用operator+=操作比较多,在于+=操作不仅可以连接单个字符,还可以连接字符串
7.4 assign
int main ( )
{
string str1 ( "hello world" ) ;
str1. assign ( "xxx" ) ;
cout << str1 << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :将空间中数据清空再添加所需内容,就是赋值的意思。如果出现空间不足问题,会自动扩容满足当前空间需求。
7.5 insert
int main ( )
{
string str1 ( "hello world" ) ;
str1. insert ( 2 , "xxx" ) ;
cout << str1 << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :从某个位置开始插入字符
7.6 erase
int main ( )
{
string str1 ( "hello world" ) ;
str1. erase ( 0 , 3 ) ;
cout << str1 << endl;
str1. erase ( ) ;
cout << str1 << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :从某个位置开始删除len个字符。如果需删除字符超过size,则有多少删多少
如果没有给具体需要删除几个字符,采用缺省值npos,默认全部删除 。留下一行空格表示,当前空间没有释放。
7.7 replace
int main ( )
{
string str1 ( "hello world" ) ;
str1. replace ( 5 , 1 , "%" ) ;
cout << str1 << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :在字符串中某个区间位置的字符进行字符替换
小结 :对于insert、erase、replace来说,底层逻辑是挪动数据,时间复杂度很高,效率很低,能不使用就不使用,建议多使用operator+=。
7.8 find
返回值:如果找到相对应的字符后,find会返回该字符所在的索引位置(从0开始的下标索引位置),如果没有匹配成功,find则会返回npos(-1);
7.8.1 size_t find(const char* s, size t pos = 0) const
size_t find ( const char * s, size t pos = 0 ) const ;
int main ( )
{
string str1 ( "file.cpp" ) ;
size_t pos = str1. find ( '.' ) ;
cout << pos << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :find从pos开始位置,查找字符串中所需字符所在位置
7.8.2 size t find(char c,size t pos =0) const
int main ( )
{
string str1 ( "https://cplusplus.com/reference/string/string/find/" ) ;
size_t pos = str1. find ( "://" , 2 ) ;
cout << pos << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :find从pos开始位置,查找字符串中所需字符串位置,并返回开头字符的下标
7.9 关于replace与find配合使用
(面试题 01.03. URL化 - 力扣(LeetCode)
int main ( )
{
string str1 ( "I am a cold boy" ) ;
size_t pos = str1. find ( ' ' ) ;
while ( pos != string:: npos)
{
str1. replace ( pos, 1 , "%20" ) ;
pos = str1. find ( ' ' ) ;
}
cout << str1 << endl;
return 0 ;
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
7.10 rfind
返回值 :如果找到相对应的字符或字符串后,rfind会返回该字符或者返回该字符串最后一个字符所在的索引位置 ;如果没有匹配成功,rfind则会返回npos(-1);
7.10.1 size_t rfind(const char* str, size_t pos = npos) const
int main ( )
{
string str1 ( "https://cplusplus.com/reference/string/string/rfind/" ) ;
size_t pos = str1. rfind ( '/' ) ;
cout << pos << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :rfind从pos开始位置,向前查找字符串中所需字符所在位置。如果没有指定该pos值,采用缺省值,从字符串最后一位开始
7.10.2 size_t rfind(const c, size_t pos = npos) const
int main ( )
{
string str1 ( "https://cplusplus.com/reference/string/string/find/" ) ;
size_t pos = str1. rfind ( "com" ) ;
cout << pos << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :rfind从pos开始位置,向前查找字符串中所需字符串所在位置,并返回字符串末尾字符索引位置 ;如果没有指定该pos值,采用缺省值,从字符串最后一位开始
7.11 substr
int main ( )
{
string file ( "string.cpp" ) ;
size_t pos = file. rfind ( '.' ) ;
string suffix ( file. substr ( pos, file. size ( ) - pos) ) ;
cout << suffix << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :在str中pos位置开始,截取n个字符,然后将其返回。
如果没有给需要截取的字符长度,默认从pos位置截取到字符串末尾位置。通常遵循左闭右开的原则 。这意味着它返回的子字符串包括起始索引,但不包括结束索引位置。
7.12 c_str
int main ( )
{
string str1 ( "hello world" ) ;
char * p = new char [ str1. size ( ) + 1 ] ;
std:: strcpy ( p, str1. c_str ( ) ) ;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :返回C格式字符串(包括’\0‘)
八、string类非成员函数
**接下来介绍以下函数不属于string类中函数,而是属于全局函数。如果需要使用需要使用对应的头文件。**这里只简单介绍两个函数
class="table-box">函数 功能说明 operator+ 尽量少用,因为传值返回,导致深拷贝效率低 operator>> (重点) 输入运算符重载 operator<< (重点) 输出运算符重载 getline (重点) 获取一行字符串 relational operators (重点) 大小比较
8.1 relational operator
# include
int main ( )
{
string str1 ( "abc" ) ;
string str2 ( "acb" ) ;
if ( str1 == str2) cout << "str1 and str2 are equal" << endl;
if ( str1 != str2) cout << "str1 and str2 are not equal" << endl;
return 0 ;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
功能 :就是大小的比较,重载compare来使用的
8.2 getline
# include
int main ( )
{
string name ( "li hua" ) ;
getline ( cin, name) ;
cout << name << endl;
}
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
getline功能 :
从流中得到字符串,解决了读取字符串遇到空格或者换行符终止问题,当然也可以使用getchar完成.
C++ 取不到空格和换行 ,默认为换行和空格是一个分隔符,自动忽略
在C++中,尽管可以使用C语言中的标准库函数如 getchar
和 getc
,但是在纯C++编程中,建议使用C++标准库提供的功能来进行输入操作。
九、VS和GCC下string结构说明
下述结构是32位平台下进行验证,32位平台下指针占4个字节
9.1 VS下string结构
string总共占28个字节,内部结构稍微复杂一点,先是有一个联合体,联合体用来:
union _Bxty
{
value_type _Buf[ _BUF_SIZE] ;
pointer _Ptr;
char _Alias[ _BUF_SIZE] ;
} _Bx;
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
由于大多数情况下字符串的长度都小于16。当创建好string对象,内部已经有了16个字符数组的固定空间,不需要通过堆创建,效率高 。(buff数组优化)
其次还有一个size_t字段保存字符串长度,一个size_t字段保存从堆上开辟空间总的容量。最后还有一个指针做一些其他事情
故总共占16+4+4+4=28个字节。
9.2 GCC下string结构
G++下的,string是通过写时拷贝实现的,string对象总共占4个字节,内部只包含了一个指针,该指针将来指向一块堆空间 ,内部包含了如下字段:
struct _Rep_base
{
size_type _M_length;
size_type _M_capacity;
_Atomic_word _M_refcount;
} ;
class="hljs-button signin active" data-title="登录复制" data-report-click="{"spm":"1001.2101.3001.4334"}">
小内存不用去堆上开,栈开空间比堆块,是在编译时就算好了,成本低。
十、选择String类的理由
在C++编程中,选择 std::string
而不是 C 风格的字符串(C-string,即使用字符数组或指针表示的字符串,如 char*
)通常是一个更好的选择。以下是几个关键原因:
安全性 :
std::string
:自动管理内存,避免了手动分配和释放内存的风险,减少了内存泄漏和缓冲区溢出的可能性。-C-string :需要手动管理内存,容易出现缓冲区溢出和内存泄漏问题,尤其是在处理长字符串或动态字符串时。
简洁性和易用性 :
std::string
:提供了丰富的成员函数,如拼接、查找、替换、截取等操作,这些操作使用方便且更符合面向对象的编程风格。-C-string :需要使用标准库函数(如 strcpy
、strcat
、strlen
等)进行操作,语法较为繁琐,不易于阅读和维护。
动态扩展 :
std::string
:自动处理字符串的大小,支持动态扩展,无需担心容量不足问题。-C-string :需要预先定义长度,动态扩展时需要手动重新分配内存,这增加了代码的复杂性和出错的可能性。
兼容性与集成 :
std::string
:与C++标准库和STL容器无缝集成,能够更好地与其他C++标准库组件协同工作。C-string :虽然与C标准库函数兼容,但与C++标准库组件的结合不如 std::string
方便。
异常处理 :
性能优化 :
std::string
:在现代编译器中,std::string
的实现经过了大量优化,能有效减少不必要的内存拷贝,提高性能。C-string :需要开发者手动进行性能优化,如内存管理、字符串拼接等,容易出错且不易维护。
总结
使用 std::string
可以显著提高代码的安全性、可读性和可维护性,同时减少了手动内存管理带来的复杂性和风险。在现代 C++ 编程中,std::string
已成为处理字符串的首选工具,除非在特定情况下(如需要与 C 代码库兼容)才会选择使用 C-string。
以上就是本篇文章的所有内容,在此感谢大家的观看!这里是店小二呀C++笔记,希望对你在学习C++语言旅途中有所帮助!
data-report-view="{"mod":"1585297308_001","spm":"1001.2101.3001.6548","dest":"https://blog.csdn.net/2302_79177254/article/details/141134919","extend1":"pc","ab":"new"}">>
评论记录:
回复评论: