STL 的string类怎么啦?

测试工程师玩转DeepSeek之Prompt 掌握这些提示词技巧,测试工程师可提升与DeepSeek的协作效率至少3倍。建议结合具体项目上下文进行二次优化,并建立团队内部的提示词知识共享库。✅ “为电商支付接口生成包含幂等性验证的测试用例,覆盖网络中断重试场景”❌ “帮我写测试用例” 阅读详情
 
STL 的string类怎么啦?

陈皓

 
前言
 
上个周末在和我的同学爬香山闲聊时,同学说到 STL 中的 string 类曾经让他备受折磨,几年前他开发一个系统前对 string 类还比较清楚,然后随着程序的复杂度的加深,到了后期,他几乎对 string 类失去了信心和信任,他觉得他对 string 类一头雾水。老实说,我几年前也有同样的痛苦(就是当我写下 《 标准C++类string的Copy-On-Write技术 》 之前的一段时间)。那时,我不得不研究那根本不是给人看的 SGI 出品的 string 类的源码,代码的可读性几乎为零,而且随着了解越深入,就越觉得 C++ 的世界中到处都是陷阱和缺陷。越来越觉得有时候那些类并不像自己所想象的那样工作。
 
为什么会发生这样的情况呢? string 类只是一个“简单”的类,如果是一些比较复杂的类呢?而这几年来, C++ 阵营声讨标准模板库中的标准 string 类愈演愈烈。 C++ 阵营对这个“小子”的争讨就没有停止过。相信在下一个 C++ 的标准出台时, string 类会有一个大的变化。
 
 
了解 string 类
 
在我们研究 string 类犯了什么毛病之前,还让我先说一下如何了解一个 C++ 的类。我们要了解一个 C++ 的类,一般来说,要从三个方面入手。
 
一、            意图( Intention )。 知其然还要知所以然, string 类的意图是什么?只有了解了意图,才知道它的思路。这是了解一个事物最重要最根本的部分。不然,你会发现它的行为并不会像你所期望的那样。 string 类的意义有两个,第一个是为了处理 char 类型的数组,并封装了标准 C 中的一些字符串处理的函数。而当 string 类进入了 C++ 标准后,它的第二个意义就是一个容器。这两件事并不矛盾,我们要需理解 string 的机制,需要从这两个方面考虑。
 
二、            规格( Specification )。 我们注意到 string 类有太多的接口函数。这是目前 C++ 阵营中声讨其最重的话题。一个小小的 string 类居然有 106 个成员接口函数。居然, C++ 标准委员会会容忍这种“ ugly ”的事情的发生?目前的认为导致“ C++ 标准委员会脑子进水”的主流原因有两点,一个是为了提高效率,另一个是为了常用的操作。
 
1) 让我们先来看效率,看看 string 类中的“ == ”操作符重载接口:
bool operator==(const string& lhs, const string& rhs);
 
bool operator==(const string& lhs, const char* rhs);
bool operator==(const char* lhs, const string& rhs);
 
头一个很标准,而后两个似乎就显得没有必要了。如果我们调用:( Str == “string” )如果没有后面两个接口, string 的构造函数会把 char* 的 ”string” 转成 string 对象,然后再调用第一个接口,也就是 operator==(str, string(“string”)) 。如此“多余”的设计只能说是为了追求效率,为了省去调用构造 / 析构函数和分配 / 释放内存的时间(这会节省很多的时间)。在后面两个接口中,直接使用了 C 的 strcmp 函数。如此看来,这点设计还是很有必要的。 string 类中有很多为了追求效率的算法和设计,比如: Copy-on-Write (参看我的 《 标准C++类string的Copy-On-Write技术 》 )等。这些东西让我们的 string 变得很有效率,但也带来了陷阱。如果不知道这些东西,那么当你使用它的时候发生不可意料的问题,就会让你感到迷茫和不知所措。
 
2) 另一个让 string 类拥有这么庞大的接口的原因是常用的操作。比如 string 类的 substr() ,这是一个截取子字符串的函数。其实这个函数并不需要,因为 string 有一个构造函数可以从别的 string 类中指定其起始和长度构造自己,从而实现这一功能。还有就是 copy() 函数,这也是一个没有必要的函数, copy 这个函数把 string 类中的内容拷贝到一个内存 buffer 中,这个方法实践证明很少有人使用。可能, 1 )为了安全起见,需要有这样一个成员把内容复制出去; 2 )设计者觉得 copy 要比 strcpy 或是 memcpy 好写也漂亮很多吧。 copy() 比起 substr() 更没有必要存在。
 
三、            实现( Implementation ) 。 C++ 标准并没有过多的干预实现。不同的产商会有不同的实现。不同的产商会考虑标准中的一件事情是否符合市场的需要,并要考虑自己的编译器是否有能够编译标准的功能。于是,他们总是会轻微或是颠覆地修改着标准。 C++ 在编译器的差异是令人痛苦和绝望的,如果不了解具体的实现,在你使用 C++ 的时候,你也会发现它并不像你所想象的那样工作。
 
只有从上述三个方面入手,你才能真正了解一个 C++ 类,而你也才能用好 C++ 。 C++ 高手们都是从这样的三个方面剖析着 C++ 现实中的各种类,并以此来验证 C++ 类的设计。
 
 
 
String 类犯了什么错?
 
string 类其实挺好的。它的设计很有技术含量。它有高的效率、运行速度快、容易使用。它有很充足的接口可以满足各式各样的法,使用起来也很灵活。
 
然而,这个 string 类似乎有点没有与时俱进,它现在的设计还保持着 10 年以前的样子, 10 年来,整个技术环境都出现很多变革,人们也在使用 C++ 的过程中得到了许许多的经验。比如:现在的几乎所有的程序都运行在一个多进 / 线程的环境中,而 10 年前主流还只是单进 / 线程的应用,这是一个巨大的变化。近几年来, C++ 阵营也在实践中取得了很多的经验,特别是模板技术,而我们的 STL 显然没能跟上脚步。
 
       首当其冲的是 string 类,目前 C++ 阵营对 string 类的声讨主要集中在下面几个方面。对于下面的这些问题, C++ 阵营还是争论不休。不过,作为一个好的程序员,我们应该在我们的设计和编程中注意一下这些方面。
 
1) 目前的标 string 类有 106 个接口函数(包括构造和析构函数),如果考虑上默认参数,那么就一共有 134 不同的接口。其中有 5 个函数模板还会产生无穷多个各种各样的函数。还有各种各样的性能上的优化。在这么从多的成员函数中,很多都是冗余不必要的。最糟糕的是,众多程序员们并不了解它们,导到要么浪费了它的优势,要么踩中了其中的陷阱。
 
2) 很多人认为 string 类提供的功能中,该有的没有,已有的又很冗余。 string 类在同一个功能上实现了多次,而有一些功能却没有实现。如:大小写不区分的比较,宽行字符( w_char )的支持,和字符 char 型数据的接口等等。
 
3) 作为一个 STL 的容器, string 类和的设计和其它容器基本一样。这些 STL 都不鼓励被继承。因为 STL 容器的设计者们的几乎都遗忘了虚函数的使用,这样阻止了多态性,也许,这也是一个为了考虑效率和性能的设计。对于 STL 容易这样的设计,大多数人表示接受。但对于 string 类,很多人认为, string 类是一个特殊的类,考虑到它被使用的频率, string 类应该得到特殊的照顾。
 
4) 还有很多人认为标准的 strng 类强行进行动态内存分配( malloc ),那怕是一个很短的字符串。这会导致内存碎片问题(我们知道内存碎片问题会让 malloc 很长时间才能返回,由于降低了整个程序的性能。而关于内存碎片问题,这是一个很严重的问题,目前除了重启应用程序,还没有什么好的方法)。他们认为, string 类的设计加剧了内存碎片问题。他们希望 string 类能够拥有自己的栈上内存来存放一些短字符串,而不需要总是去堆上分配内存。(因为用于 string 类的字符串长度几乎都不会很长)
 
5) 很多 string 类的实现,都采用了 Copy-On-Write ( COW )技术。虽然这是一个很有效率的技术。但是因为内存的共享,导致了程序在“多线程”环境中及容易发生错误,如果分别在两个线程中的 string 实例共享着同一块内存,很有可能发生潜在的内存问题(参看我的 《 标准C++类string的Copy-On-Write技术 》最后一节示例 )。目前这一技术很有可能从下一版本的标准中移去。(而一些新版本的 STL 都不支持 COW 了,如 Microsoft VC8.0 下的 STL )
 
6) 标准的 string 类不支持 policy-base 技术的错误处理。 string 遇到错误时,只是简单地抛出异常。虽然这是一个标准,但有一些情况下不会使用异常( GCC –fno-exception )。另外,不可能要求所有的程序都要在使用 string 操作的时候 try catch ,一个比较好的方法是 string 类封装有自己的 error-handling 函数,并且可以让用户来定义需要使用哪一种错误处理机制。
 
 
由于 string 类的的种种不如人意,特别是 106 个接口函数让许多人难以接受,有很多人都在写适合自己的 string 类。但总体来说,标准的 string 类是一个好坏难辨的类。无论你是否是一个高级咨深的程序员,你都会用到它。它和整个 C++ 一样,都是一把双刃剑,在大多数情况下,它还是值得我们信赖。
 
目前,对 string 类的争论有很多很多。 C++ 标准委员会也说:“ The C++ Standard is the best we could make it. If we could have agreed on how to make it better, then we would have made it better. ”在 C++ 这么一个混乱的领地,虽然 STL 并不完美,但对比起来说,他还是显得那么地漂亮和精致辞。
 
 
后记
 
又到了关于 C++ 文章结束的时候,我还是要老调重弹。 C++ 这个世界是很复杂很危险的。单单本文章中的一个小小的 string 类就能引起这么多的讨论,何况是别的类?
 
让我们大胆地怀疑一下, C++ 是否真是一种高级的语言?目前的 C++ 需要使用他的人有相当的专业技术水平,而寄希望于人的高水平看来是和技术的发展背道而驰的。好的一门开发语言是让人可以容易方便地把更多的精力集中在业务逻辑性上。而 C++ 这门语言却需要技术人员比以住的 C 有着更为高深和专业的技术知识和能力。
 
是我们对 string 的“无知”搞乱了我们的程序,还是 string 这个类的设计把我们的程序搞乱了?是 C++ 自己把软件开发搞得一团混乱?还是使用 C++ 的人把其搞得一团混乱?好像兼而有之,目前我们无法定论,但我们知道,无论是 C++ 标准委员会,还是开发人员,大家的 C++ 未来之路都还有很长。
 
 
( 转载时请注明作者和出处。未经许可,请勿用于商业用途 )
更多文章请访问我的 Blog: http://blog.csdn.net/haoel
 
 
TensorFlow实战:5步搞定因果推断模型TARNet(附完整代码) 本文提供了一份基于TensorFlow的TARNet因果推断模型实战指南。通过五个清晰步骤,从数据预处理、模型构建到训练评估,详细讲解了如何利用深度模型解决营销评估、疗效分析等场景中的因果效应估计问题,并附有完整代码解决样本不平衡等工程挑战。 阅读详情

相关推荐

el-transfer和el-tree进行结合搞一个树形穿梭框

由于业务需求需要在穿梭框里使用树形结构,但是本身element里并不支持,于是参考了别的大佬发的文章作为思路及后续自己新增了一些处理功能。

bbkhhvv的博客 6302

转载:陈皓:C++ STL STRING的COPY-ON-WRITE技术(写时拷贝)

转载:陈皓:C++ STL STRING的COPY-ON-WRITE技术(写时拷贝)

wihkum 363

同济大学C++mooc第五、六讲参考答案

同济大学C++moooc第5、6讲 第五讲 第一题 随机产生10个30~100(包括30,100)的正整数,求它们的最大值、最小值、平均值,并显示整个数组的值和结果。 代码片. // #include<iostream> const int n = 10; using namespace std; int main() { int s[n],i,j,t,sum=0; for (i = 0; i < n; i++)

cjzui6666的博客 1万+

gcc 4.8.5 的string问题

gcc 4.8.5的调用

lanxiaziyi的专栏 1223

华为防火墙双ISP出口实战:如何用策略路由实现电信联通流量自动切换(附配置截图)

本文详细解析了华为防火墙在双ISP环境下的智能选路技术,通过策略路由与健康检测的深度应用,实现电信联通流量的自动切换。文章包含实战配置截图,帮助企业解决切换延迟、路径劣化等核心挑战,提升业务连续性。

backprop5master的博客 636

10分钟上手YOLOv11:最强姿态估计模型来了,代码开源,效果炸裂!

【10分钟玩转YOLOv11实时姿态估计】🚀 YOLOv11作为YOLO家族最新成员,在速度、精度和易用性上全面升级,尤其适用于姿态估计等复杂视觉任务。本文带您快速掌握: 1️⃣ 核心概念:姿态估计即识别人体17个关键点(如关节部位)并连接成数字骨架,是智能健身、体感游戏等应用的基础。 2️⃣ 技术优势: 超轻量级(最小仅2.9M参数) 极速推理(GPU仅1.7ms) 高精度(COCO mAP@50-95达50%) 3️⃣ 三步实操: ① 安装:pip install ultralytics ② 准备人物

weixin_41246802的博客 1772

【C++】-- STL之String详解

STL(standard template libaray-标准模板库):是C++标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。 模板是C++程序设计语言中的一个重要特征,而标准模板库正是基于此特征。标准模板库使得C++编程语言在有了强大的类库的同时,保有了更大的可扩展性。 STL有6大组件: ​ 其中,容器、算法、迭代器、函数是很重要的部分,有了STL,许多底层的数据结构以及算法都不需要自己重新造轮子,站在前人的肩膀上,肯定飞的更快嘛..

局部变量和全局变量 3880

告别JavaScript!C#通过WebAssembly在浏览器中实现“原生级“性能

C# + WebAssembly:前端开发的革命性替代方案 摘要:本文探讨了C#通过WebAssembly取代JavaScript开发前端应用的新趋势。文章分析了JavaScript的局限性(弱类型、回调地狱等),并详细介绍了C#+WebAssembly组合的优势:强类型系统、高性能、多线程支持和代码重用。技术实现方面,阐述了C#通过Mono/.NET编译为WebAssembly字节码的原理,重点介绍了Blazor框架的两种模式。文章还提供了实战指南,包括项目创建、多线程配置,以及一个与ChatGPT AP

墨夶的博客 943

【C++】---STL之string详解

什么是STL?STL(standard template libaray-标准模板库):是C++标准模版库C语言中,字符串是以’\0’结尾的一些字符的集合。string是表示字符串的字符串类该类的接口与常规容器的接口基本相同,再添加了一些专门用来操作string的常规操作。string在底层实际是:basic_string模板类的别名,typedef basic_string<char, char_traits, allocator> string;不能操作多字节或者变长字符的序列。

weixin_75128035的博客 2031

【模型实战】MiMo-VL-7B讲解与实战

维度成绩MMMU70.6(图像理解最难测试之一)VideoMME70.8(视频理解标杆)59.4(超越78B参数模型)56.1(超过专用GUI模型)Elo评分开源VLM排名第一(7B~72B)社区热度过去一个月下载超1,600次(RL+SFT)📌一句话概括MiMo-VL 是目前性能最强、推理最稳、体验最佳、生态最全的7B级开源视觉语言模型。

m0_47867638的博客 1188

【DRAM存储器四十六】LPDDR5介绍--基本操作之行操作、读、写

简述LPDDR5的行操作和读写时序

highman110的博客 755

STL 的string类怎么啦

用起来像容器——有begin()end()size(),可以放进,也能配合std::sort——但它又和c_str()返回的指针有特殊生命周期,在不同标准库上不同,operator[]不检查越界,某些操作还会让所有迭代器失效。并不是「STL 容器」这个分类里和vectorlist完全平级的一员。它是的别名,定义在<string>中,是一个独立的类模板,提供了大量字符串特有的接口(查找、替换、子串、数值转换)。

m0_74824496的博客 8

RK3568平台开发系列讲解(音频篇)配置声卡

📢本篇文章介绍如何配置声卡。

内核笔记 2442
上一篇: 从语句 char* p="test" 说起
下一篇: 其实Unix很简单
haoel
haoel 领域专家: 系统编程技术领域 领域专家: 系统编程技术领域 业界专家认证 业界专家认证
博客等级 码龄27年 2万+粉丝 120原创
评论 24
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值