effective stl 第15条

9 篇文章 0 订阅

第15条 注意string实现的多样性

实现string的方式很多。

几乎每个string实现都包含如下信息:

1)字符串的大小(size),即它所包含的字符的个数。

2)用于存储该字符串中字符的内存的容量(capacity)。

3)字符串的值(value),即构成该字符串的字符。

除此之外,一个string还可能包含:

4)它的分配子的一份拷贝。这个字段是可选的。

建立在引用计数基础上的string实现可能还包含:

5)对值得引用计数。

书中写了4种string的实现,结构依次如下:

实现A:包含其分配子的一份拷贝 该字符串的大小 它的容量,以及一个指针,该指针指向一块动态分配的内存,其中包含了引用计数(refCnt)和字符串的值。

在该实现中,使用默认分配子的string对象大小是一个指针的4倍。若使用了自定义的分配子,则string对象会更大一些,多出的部分取决于分配子对象的大小。



实现B: string对象与指针大小相同,因为它只包含一个指向结构的指针。这里嘉定使用了默认的分配子。如果使用了自定义的分配子,则string对象的大小将会相应的加上分配子对象的大小。在该实现中,由于用到了优化,所以使用默认的分配子不需要多余的空间。而实现A中没有这种优化。

B的string所指向的对象中包含了该字符串的大小,容量和引用计数,以及一个指向一块动态分配的内存的指针,该内存中存放了字符串的值。该对象还包含了一些与多线程环境下的同步控制相关的额外数据。这些数据暂不讨论,标记为“其他”。


标记为“其他”的数据块比其他的要大。用于实现同步控制的数据是指针的大小的6倍。


实现C:string对象的大小总是与指针的相同,而该指针所指向一块动态分配内存,其中包含了与该字符串相关的一切数据:它的大小,容量,引用计数和值。没有用对单个对象的分配子支持。该内存中也包含了一些与值的可共享性相关的数据。这里不考虑,标记为“X”。


实现D:string对象是指针的大小的7倍(仍然假定使用的是默认的分配子)。这一实现不使用引用计数,但是每个string内包含一块内存,最大可容纳15个字符的字符串,小字符串可以玩转的存放在该string对象中,这一特性成为”小字符串优化“特性。当一个string的容量超过15时,该内存的起始部分被当做一个指向一块动态分配的内存的指针,而该string的值就放在这块内存中。


例如一个strings(“pause”);

在实现D中不会导致任何动态分配,在A和C中将导致一次动态分配,而在B中江导致两次动态分配(1次为string对象所指向的对象,另一次是为该对象所指向的字符缓冲区),但是B包含了对多线程系统中同步的支持,所以自己要选用哪种实现,需要结合自己的需要,选择不同的实现版本。

在以引用计数为基础的设计方案中,string对象之外的一切都可以被多个string共享,所以我们还可以得出,A比B或C提供了较小的共享能力,B和C可以共享string的大小和容量,从而见笑了每个对象存储这些数据的评价开销。D中所以的string不共享任何数据。

不同实现的区别有:

1) string的值可能会被引用计数,也可能不会。很多实现在默认情况下回使用引用计数,但它们通常提供了关闭默认选择的方法,往往是通过预处理宏来做到这一点的。第13条给出了想将其关闭的一种特殊情况,但其他的原因也有可能。比如,只有当字符串被频繁复制时,引用计数才有用,而有些应用并不经常复制内存,这就不值得使用引用计数了。

2) string对象大小的范围可以是一个char*指针的大小的1到7倍。

3) 创建一个新的字符串值可能需要0次,一次或两次动态分配内存。

4) String对象可能共享,也可能不共享其大小和容量信息。

5) String可能支持,也可呢过不支持对单个对象的分配子(C不支持)

6) 不同的实现对字符内存的最小分配单位有不同的策略。



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值