学习 LLVM(4) StringRef 类

类 StringRef 定义在文件 llvm/include/ADT/StringRef.h 中

== 说明 ==
StringRef 数据类表示一个固定不变的字符串的引用(包括一个字符数组的指针和长度),它支持可用在 std::string 类上的各种通用字符串操作,但是不需要进行内存的分配。所引用的字符串不需要以 null 字符结尾。

StringRef 自己不拥有字符串数据,在使用 StringRef 的时候期望字符串放在别的地方,而存放的地方的声明周期要超过 StringRef 的。因此,一般保存 StringRef 自己是不安全的。

StringRef 可以引用一个外部实际字符串的一部分,例如 const char *s = "abcdefg",
StringRef(s+1, 4) 表示引用从s+1 位置开始的长度为 4 的子字符串,也即 "bcde"。

参见:http://llvm.org/docs/ProgrammersManual.html#StringRef

== 实现 ==
StringRef 的实现简化如下:

class StringRef {
  const char *Data;  // 字符串的开始位置,指向一个外部的缓冲区(不属于 StringRef 管理)
  size_t Length;   // 字符串的长度。

  StringRef(...)   // 多种形态的构造函数
  
  data(), size()   // 获得 Data, Length 的 inline 函数。
  begin(), end(), empty(), size(), front(), back(), [] 等类似于 STL 容器标准方法的函数。
  equals(), compare(), startswith(), find(), substr(), split() 等一般字符串操作
  std::string, str()  // 转换为标准 std::string
  // 其它略
}
多个 StringRef 二元操作符 operator <, >, ==, !=, >=, <=, += 的重载。
模板 isPodLike<StringRef> 的特化,可将 StringRef 作为 POD 数据对待。

 

* StringRef 实例比较小(sizeof 值为 8),它足够小因而可以直接作为参数传递,或作为返回值类型。

== 为何要设计 StringRef 类等问题 ==
* 我认为是 LLVM 在设计和实现上高度追求性能,在类的设计使用上力求精确、高效。在一些场合,字符串已知有拥有者,需要传递其全部或部分字符串到别的函数,此时,使用 StringRef 可以减少字符串分配、分割、裁剪等各种操作带来的空间需求。
* StringRef 中保存了字符串长度 Length 信息,因此在计算 strlen() 的时候能够节省一些时间,从而提高对长字符串计算长度时的性能。而且可以支持中间带有 null 字符的字符串。
* 配合 Twine 类,StringRef 的各种操作可能更有价值。

* 然而我在代码中也看到过对 std::string 进行 StringRef 引用,而后在另一个地方再次使用 str() 函数得到新分配的 std::string,这样不良的使用也会造成不必要的多次重复分配。有什么更好的办法来解决这种问题吗?

你可能感兴趣的:(llvm)