C++ string详解:从底层原理到常用操作全面掌握std::string
1. 什么是string在C中字符串有两种表示方式C风格字符串C-style stringC标准库提供的string类C语言中使用字符数组表示字符串char str[] hello;本质上h e l l o \0字符串末尾需要一个\0表示结束。但是C风格字符串存在很多问题需要手动管理空间容易发生越界字符串拼接复杂容易造成内存泄漏例如char str1[20] hello; char str2[] world; strcat(str1, str2);程序员必须提前考虑数组空间是否足够。C提供了std::string类解决这些问题。使用#include iostream #include string using namespace std; int main() { string s hello; cout s endl; return 0; }输出hellostring本质上是一个管理字符数组的类。它帮我们完成动态扩容内存释放字符串拼接查找替换长度管理2. string的底层结构string内部大致包含class string { private: char* _str; // 指向字符串空间 size_t _size; // 当前有效字符数量 size_t _capacity; // 容量 };例如string s hello;内存类似_str | v ------------------- | h | e | l | l | o | \0 | ------------------- size 5 capacity 5注意size表示有效字符数量。capacity表示当前申请的空间大小。例如string shello; couts.size()endl; couts.capacity()endl;可能输出5 15说明虽然字符串只有5个字符但是内部可能提前开辟15个空间。3. string的构造函数3.1 默认构造创建空字符串string s;相当于3.2 使用字符串初始化string s(hello);或者string shello;3.3 拷贝构造string s1hello; string s2(s1);结果s1: hello s2: hello两个对象内容一样。3.4 创建n个相同字符格式string(size_t n,char c);例如string s(5,a); couts;输出aaaaa4. string容量相关接口size()返回字符串长度string shello; couts.size();输出5length()功能和size一样couts.length();推荐size()因为STL容器统一使用size。capacity()查看容量string shello; couts.capacity();empty()判断是否为空string s; if(s.empty()) { cout空字符串; }clear()清空字符串string shello; s.clear(); couts;结果注意clear只是清除内容。不会释放空间。例如string shello; couts.capacity(); s.clear(); couts.capacity();容量通常不变。5. string访问字符operator[]最常用string shello; couts[0];输出h修改s[0]H; couts;结果Helloat()和[]类似couts.at(0);区别[]越界不会检查。at():越界会抛异常。例如string shello; couts.at(100);会产生out_of_range异常6. string遍历方法1for循环string shello; for(size_t i0;is.size();i) { couts[i] ; }输出h e l l o方法2范围forC11支持for(auto ch:s) { coutch; }方法3迭代器string shello; string::iterator its.begin(); while(it!s.end()) { cout*it; it; }7. string拼接operator最简单string s1hello; string s2world; string s3s1s2; couts3;输出helloworldappend()追加字符串string shello; s.append( world); couts;输出hello worldpush_back()尾插一个字符string shello; s.push_back(!); couts;输出hello!注意push_back只能插入一个字符。错误s.push_back(abc);8. string插入insert()格式insert(pos,string)例如string shello; s.insert(5, world); couts;结果hello world9. string删除erase()删除指定位置string shello; s.erase(1,2); couts;过程删除e l结果hlo格式erase(pos,len)删除最后一个字符s.pop_back();例如string shello; s.pop_back(); couts;输出hell10. string查找find()查找字符串string shello world; size_t poss.find(world); coutpos;输出6如果找不到返回string::npos例如if(s.find(abc)string::npos) { cout不存在; }rfind()从后往前查找string shello hello; couts.rfind(hello);输出611. string替换replace()格式replace(pos,len,string)例如string shello; s.replace(0,5,world); couts;结果world12. string截取子串substr()格式substr(pos,len)例如string shello world; string subs.substr(6,5); coutsub;输出world13. string和C字符串转换string转char*不能直接string shello; char* ps;错误。使用s.c_str();例如string shello; printf(%s,s.c_str());char*转string直接char str[]hello; string sstr;即可。14. string的扩容机制当字符串空间不足时旧空间 | v [hello] 插入: [hello world] 重新申请更大空间 复制数据 释放旧空间类似vector。扩容通常是1.5倍 或者 2倍不同编译器实现不同。例如string s; for(int i0;i100;i) { s.push_back(a); couts.capacity()endl; }可以观察容量变化。15. string为什么比char数组方便char数组char a[100]; strcpy(a,hello); strcat(a,world);问题容易越界不知道长度需要手动管理stringstring shello; sworld;优势自动管理内存接口丰富安全性更高支持STL算法16. string使用注意事项1. size返回unsigned类型例如错误for(int is.size()-1;i0;i--)因为size_t是无符号类型可能导致死循环。推荐for(int i(int)s.size()-1;i0;i--)2. 修改字符串不能越界错误string shello; s[10]a;属于非法访问。3. 不要频繁拼接大字符串例如string s; for(int i0;i100000;i) { shello; }可能频繁扩容。优化s.reserve(500000);提前开空间。17. reserve和resize区别这是string里面非常重要的知识。reserve()改变容量string s; s.reserve(100);结果capacity100 size0不会初始化字符。resize()改变有效字符数量string s; s.resize(10);结果size10里面产生10个\0。区别接口改变是否初始化reserve容量否resize大小是18. string总结功能接口长度size()容量capacity()清空clear()判断为空empty()访问字符[]、at()尾插字符push_back()删除尾字符pop_back()拼接、append()插入insert()删除erase()查找find()替换replace()截取substr()预留空间reserve()调整大小resize()总结std::string是C中最常用的字符串类它本质上是一个动态管理字符数组的类。学习string不仅是学习几个接口更重要的是理解string如何管理内存size和capacity区别扩容机制深浅拷贝问题STL容器设计思想掌握string以后可以为后续学习vectorlistmapunordered_mapSTL算法打下非常好的基础。一句话总结C语言告诉我们字符串是什么C string告诉我们如何优雅、安全、高效地管理字符串。

相关新闻