1. 使用场景
- 如果是不需要修改的字符串常量,使用C原生字符串,如:打印日志
- 如果需要修改就使用SDS
2. 为何使用SDS代替C字符串
2.1 C字符串缺点
- 不记录自身长度,每次获取都要计算,直到遇到代表字符串结尾的空字符串为止,时间复杂度为O(n)
- 由于不记录自身长度,在字符串拼接时如果不提前分配内存就会造成溢出
- 频繁的对字符串进行修改时,会频繁的进行内存重新分配
- 不能保存空字符,否则会认为是字符串结束
2.2 更加完善的SDS
针对C字符串的缺点,SDS做了响应的拓展,先看定义:
2.2.1 定义
struct sdshdr{
//记录buf数组中已经使用字节的长度
//等于SDS保存字符串长度
int len;
//记录buf数组中未使用字节长度
int free;
//字节数组,用来保存字符串
char buf[];
}
- free为0,表示该字符串所有空间都已经使用
- len为5表示,保存了5个
字节
的字符串 - buf是char类型数组,数组保存了’R’、‘e’、‘d’、‘i’、‘s’五个字符,最后一个字节保存空字符’\0’
保存空字符是为空沿用C字符串的一些方法
2.2.2 SDS针对C字符串的升级
- len属性保存了字节长度,获取长度的时间复杂度为O(1),设置和更新len是由API执行时自动完成的
- 每次修改字符串时会检查长度,杜绝了缓冲区溢出
- 减少了修改字符串带来内存重新分配次数
- 空间预分配:如果对SDS修改后,len小于1MB,同样会分配len属性同样大小的未使用空间;如果大于1MB,机会分配1MB未使用空间,即len=1MB
- 惰性释放:SDS缩短操作时,不会马上释放多出来的字节,而是使用free属性记录起来,等待将来使用
- 二进制安全:SDS的API会以处理二进制的方式处理buf数组中数据,存进去什么样子,拿出来就是什么样子,可以保存空字符,即可以保存文本,也可以保存任意二进制数据
3. 总结
SDS较于C字符串有以下优势:
- 获取长度复杂度为O(1)
- 缓冲区不会溢出
- 减少字符串修改时内存重新分配次数
- 二进制安全
- 兼容部分C函数