在我看来,许多更大的C ++库最终都创建了自己的字符串类型。在客户端代码,你要么必须使用从库中一个(QString
,CString
,fbstring
等,我相信任何人都可以仅举几例)或保持标准型和一之间进行转换的库使用(其中大部分时间涉及至少一份)。
那么,是否存在某种特定的功能缺陷或某些错误之处std::string
(就像auto_ptr
语义不好一样)?它在C ++ 11中有变化吗?
java.lang.String
(缺少运算符重载等)会使使用其他任何内容变得很痛苦。
在我看来,许多更大的C ++库最终都创建了自己的字符串类型。在客户端代码,你要么必须使用从库中一个(QString
,CString
,fbstring
等,我相信任何人都可以仅举几例)或保持标准型和一之间进行转换的库使用(其中大部分时间涉及至少一份)。
那么,是否存在某种特定的功能缺陷或某些错误之处std::string
(就像auto_ptr
语义不好一样)?它在C ++ 11中有变化吗?
java.lang.String
(缺少运算符重载等)会使使用其他任何内容变得很痛苦。
Answers:
大多数较大的C ++库都是在std::string
标准化之前启动的。其他功能包括后来被标准化或尚未标准化的其他功能,例如对UTF-8的支持以及编码之间的转换。
如果这些库在今天实现,它们可能会选择编写对std::string
实例进行操作的函数和迭代器。
char
确保足够大以容纳任何UTF-8代码点。AFAIK,这是C ++ 98提供的唯一“支持”。
wchar_t
是不是大到足以代表所有Unicode代码点。此外,关于UTF-16的整个讨论都被认为是有害的,在该论点上,非常有说服力的论点认为 应该只使用UTF-8 …
字符串是C ++的最大尴尬。
在最初的15年中,您根本不提供字符串类-强制每个平台上的每个编译器和每个用户创建自己的字符串类。
然后,对于应该是完整的字符串操作API还是仅仅是STL char容器,您会产生一些困惑,因为有些算法会复制std :: Vector上的算法或其他算法。
在明显的字符串操作(例如replace()或mid())涉及如此多的迭代器的情况下,您需要引入新的'auto'关键字以使语句适合单个页面,并导致大多数人放弃整个语言。
然后,您有了unicode'support'和std :: wstring,这只是个错误.....
<离开>谢谢-我现在感觉好多了。
std::string
。1983年缺少String类并不能证明现在有更多的此类。
实际上...存在一些问题std::string
,是的,它在C ++ 11中会变得更好一些,但请不要超越自己。
QString
并且CString
是旧库的一部分,因此它们在C ++标准化之前就已经存在(很像SGI STL)。因此,他们必须创建一个类。
fbstring
解决非常具体的性能问题。该标准规定了一个接口,算法的复杂性保证了最低限度,但是无论最终是否快速,这都是实施质量的细节。fbstring
具有特定的优化(find
例如与存储相关的或更快的)。
其他未引起关注的问题(en vrac):
std::string
没有编码,并且没有UTF-8的特殊代码,很容易在其中存储UTF-8字符串并无意间破坏它std::string
接口是ated肿的,许多方法本可以实现为自由功能,并且许多方法被复制以符合基于索引的接口和基于迭代器的接口。c_str()
返回指向连续存储的指针,该指针提供了一些C的互操作性。但是,您不能修改指向的数据。典型的解决方法包括使用vector<char>
。
&s[0]
就不再重要了:)
&s[0]
可能未指向以NUL终止的字符串(除非c_str()
自上次修改以来已被调用)。
c_str()
返回:这样的指针p
,p + i == &operator[](i)
用于i
in 中的每个[0,size()]
。
除了这里发布的原因之外,还有另一种二进制兼容性。图书馆的作者无法控制std::string
您使用的是哪种实现,以及它是否具有与他们相同的内存布局。
std::string
是一个模板,因此其实现是从本地STL标头中获取的。现在,假设您在本地使用一些性能经过优化的STL版本,该版本与标准完全兼容。例如,您可能选择在每个静态缓冲区中插入静态缓冲区std::string
以减少动态分配和高速缓存未命中的次数。结果,实现的内存布局和/或大小与库的不同。
如果仅布局不同,std::string
则从库传递到客户端的实例上的某些成员函数调用可能会失败,反之则可能失败,具体取决于转移的成员。
如果大小也不同std::string
,则在库和客户端代码中进行检查时,所有具有成员的库类型都将具有不同的sizeof。跟随std::string
成员的数据成员的偏移量也将偏移,并且从客户端调用的任何直接访问/内联访问器都将返回垃圾,尽管在调试库本身时“看起来不错”。
底线-如果库和客户端代码std::string
再次编译为不同版本,则它们将链接得很好,但是可能会导致一些令人讨厌且难以理解的错误。如果更改std::string
实现,则必须重新编译STL中公开成员的所有库,以匹配客户端的std::string
布局。而且由于程序员希望他们的库更强大,因此几乎看不到std::string
任何地方公开的内容。
公平地说,这适用于所有STL类型。IIRC他们没有标准化的内存布局。
这个问题有很多答案,但是这里有一些:
遗产。在存在std :: string之前,已编写了许多字符串库和类。
为了与C中的代码兼容。库std :: string是C ++,其中还有其他与C和C ++一起使用的字符串库。
避免动态分配。std :: string库使用动态分配,可能不适合嵌入式系统,中断或实时相关代码或低级功能。
模板。std :: string库基于模板。直到不久以前,许多C ++编译器的性能还很差,甚至还没有足够的模板支持。不幸的是,我在一个使用大量自定义工具的行业中工作,而来自该行业主要参与者的我们的工具链之一并没有“正式”地100%支持C ++(有错误的东西是模板等)。
可能还有许多更正当的理由。
主要是关于Unicode。对Unicode的标准支持充其量是极差的,每个人都有自己的Unicode需求。例如,ICU支持您可能想要的所有Unicode功能,在您可能想像到的最令人讨厌的自动从Java生成接口的背后,如果在Unix上使用UTF-16,则可能不是您的想法美好时光。
此外,许多人需要不同级别的Unicode支持-并非每个人都需要复杂的文本布局API等。因此,很容易看出为什么存在大量的字符串类-标准类非常糟糕,每个人都有与新类不同的需求,没有人设法创建一个可以通过令人愉悦的界面执行许多Unicode支持跨平台的类。
在我看来,这主要是C ++委员会在1998或2003年没有正确提供对Unicode的支持的错,也许这是可以理解的,但是在C ++ 11中却不是。希望在C ++ 17中它们会做得更好。
这是因为每个程序员都有一些要证明的事情,并且感到有必要为自己的一个很棒的函数创建自己的很棒的,更快的字符串类。根据我的经验,它通常是多余的,并导致各种额外的字符串转换。