Table of Contents
概要
理解String(BasicString)
关于TempString基类
源码
参考阅 读
概要
我们知道,C++标准库(STL)提供了string(basic_string)类进行字符串操作。字符串很可能除了内存 分配器(allocator)1外使用最为频繁的STL类。但是C++社区对string的指责从来就没有停止过。
归纳起来,STL的 string类主要有以下这些争议点:
接口过多且规格和其他STL容器没有达成很好的一致性。例如,string::find使用下标 ,而不是以iterator作为迭代位置,这和其他容器不太一样。
内存碎片。由于过于频繁的字符串构造、析构,导致系统 的内存碎片现象严重。
Copy -On-Write与多线程安全。string(basic_string)基于Copy-On-Write技术的原因,是因为 string的赋值被设计成为低开销的。但是一旦考虑到多线程安全问题,Copy-On-Write会把大量的时间花在锁的开销上。一些新 的STL实现 (如SGI STL)放弃了基于Copy-On-Write的string实现。
我认同这些指责。字符串最好的设计,还是将 string分拆为一个常字符串(std::String)和一个字符串操作类(StringBuilder)。我们的StdExt库这样做了。
理解 String(BasicString)
StdExt的String(BasicString),和你以前见过的所有字符串类都不太一样。这个类比你想象 的还要简单,它只有两个成员变量:
template <class _E>
class BasicString
{
const _E* m_pszBuf;
size_t m_length;
};
它区别于string(basic_string)之处在于:
它是一个常字符串,它永远不会试图去篡改字符串内容 (m_pszBuf指向的数据)。
它没有析构,你可以认为其实只是一个结构体。当然,为了方便,BasicString还是有构造函 数。
它的m_pszBuf不以nil为结束。而是由m_length成员限定字符串的长度。
它不维护字符串内容(m_pszBuf) 的生命周期。如上所述,它没有析构,任何时刻它只是接受或者生成字符串内容,但是不负责销毁它。
最后一点非常重 要,也是它的特别之处:它并不维护字符串的生命周期。这可能让你诧异:居然会有这样字符串类,它并不管理字符串的生命周 期。
但是我们这样做了。而这的确给我们带来很多便利。例如:
赋值(复制)、子串(substr)是非常轻量的操 作。Copy-On-Write技术完全是多余的。
可以将任意的线性容器(如std::vector、std::basic_string)临时转换为 String(非常轻量)。参见下文中对String::cast方法的介绍。
为什么String类可以不管理自己的生命周期?这就是我 们StdExt的内存管理变革倡导的思想了。
浏览下String类的参考手册,你注意到有这样两个构造函数:
BasicString(const value_type* pszVal, size_type cch);
template <class AllocT>
BasicString(AllocT& alloc, const value_type* pszVal, size_type cch);
这表示:第一个构造函数传入 的pszVal,其生命周期比BasicString长(到BasicString析构时仍然有效)。而第二个构造函数的意思是,pszVal是一个临时有 效的字符串,这个构造函数将拷贝一个pszVal字符串的副本。
为什么不支持 BasicString(const value_type* pszVal) 这样的构造?
很简单,这个构造过于危险,我不能确定你的意图是什么。
关于TempString基类
从字面意 思来讲,这是一个临时字符串类。为什么它会是String(即BasicString)的基类?这其实只是实现上的需要。TempString理论 上就是String(只是有特殊的生命周期),和BasicString规格一致。之所以它最后成为BasicString的基类,完全是实现上方便 的考虑。
以BasicString::compare为例,我们考察以下这个函数:
int BasicString::compare(const TempString<_E> b) const;
这个函数的含义非常丰富。相当于定义了以下这一系列的函数:
int BasicString::compare(const _E& b) const; // 与包含单个字符b的字符串比较
int BasicString::compare(const _E* b) const; // 与C Style风格的字符串b比较
int BasicString::compare(const basic_string<_E>& b) const; // 与STL string比较
int BasicString::compare(const BasicString<_E>& b) const; // 与另一个常String比较
int BasicString::compare(const vector<_E>& b) const; // 与向量表示的字符串b比较
int BasicString::compare(const BasicStringBuilder<_E>& b) const;
一个函数可抵6个函数!