首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >C++string: SBO 和 引用记数的写时拷贝

C++string: SBO 和 引用记数的写时拷贝

作者头像
君辣堡
发布2025-12-20 09:38:09
发布2025-12-20 09:38:09
170
举报

1.SBO    小对象优化

在了解SBO,先来看看这道题:

s1 和 s2 ,谁更大?

在刚学习C++string,就容易陷入误区,觉得s2更大,因为它有数据。

但数据真的存储在string本身吗?并不是,它存储在一片堆空间内,由stirng内部的指针指向该空间  我们之前实现了简单string,其底层是_str,_size,_capacity  按照指针是4/8字节,整型是4字节

那答案会是12 / 16 吗?   

答案是28 ,两个都是28  (VS2019 , 32位系统下) 那么这是为什么?通过VS编译器我们可以发现:

如图,看右边可以发现,其底层多了一个字符串数组:_Buf   ,16个字符的字符串数组,可存储有效字符数为15

一旦字符串存入的有效字符数大于15,_Buf存不下了,就会转到_Ptr 内

这就是SBO     小对象优化

SBO本质是以空间换时间。   对象比较小时,就不去堆上开空间,存在_Buf 上 比去堆上开空间更省时间,缺点是可能浪费空间。

如果对象太大 ,就在堆上开空间,并用_Ptr 指向该空间。不会两边都存一点,只会选择一边存储

因此,如果有SBO就需要判断字符串存在哪,有效字符数 >=15 就是存堆空间上,小于15 就是存_Buf 上


2.写时拷贝

写时拷贝就是一种拖延症,是在浅拷贝的基础之上增加了引用计数的方式来实现的。

2.1引用记数

引用计数:用来记录资源使用者的个数。在构造时,将资源的计数给成1,每增加一个对象使用该资源,就给计数增加1,语言可能有点抽象,看图理解:

就是这片空间的使用者,每多一个,引用记数就+1,s1构造时,引用记数变成1 ,s2拷贝构造的浅拷贝,使s2也指向这空间,那引用记数变成2

也就是说,引用记数是用来避免多次析构的

当某个对象被销毁时,先给该计数减1,然后再检查是否需要释放资源(空间), 如果计数为1,说明该对象是资源的最后一个使用者,那他就负责这片资源的析构,释放资源;否则就不能释放,因为还有其他对象在使用该资源(重复析构)

有了上图的解释,相信这句话就好理解很多。


2.2引用记数的写时拷贝

现在我们来了解写时拷贝。写时拷贝,那就是  在写的时候才拷贝

如图,s2,s1都指向同一片资源 "hello world" 

如果此时我们要修改资源,那就会使s2也被修改,那写时拷贝的作用就来了:如果引用记数是1,那就直接写(修改

如果引用记数不是1,那就得老实深拷贝

那最终还是要深拷贝,为什么这么麻烦,还搞引用记数?

其实这就是在赌你不需要深拷贝。因为深拷贝的代价很大,(早年编译器不优化深拷贝时)需要来回释放开辟空间,如果你不需要深拷贝,浅拷贝能完成,那就不深拷贝。实在不行再深拷贝。这样提高了效率,不需要干什么都深拷贝。  


2.3写时拷贝的弊端

在下面3点,引用记数就很麻烦,甚至不好:

现阶段还理解不了,目前了解

string完结,后面会开始讲STL:vector ,感谢支持

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.SBO    小对象优化
  • 2.写时拷贝
    • 2.1引用记数
    • 2.2引用记数的写时拷贝
    • 2.3写时拷贝的弊端
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档