abseil strings/string_view 源码分析
Revision:
- LTS_20210324.2
- 278e0a071885a22dcd2fd1b5576cc44757299343
这个模块是 absl 提供的和 C++ 17 保持兼容的 string_view 实现。
NUL-Terminated String Length Computation
主要用于从一个 null-terminated c-style string 构造 string_view 的重载
1 | constexpr string_view(const char* str); |
因为要考虑 constexpr
-ness,所以大多时候都不会使用 trivial strlen()
。
1 | static constexpr size_type StrlenInternal(const char* str) { |
MSVC 上手动实现一个 constexpr length()
GCC & Clang 上直接使用 __builtin_strlen()
💡 C++ 17 开始
char_traits::length()
是constexpr
,所以如果只考虑 C++ 17 之后的场景,应该可以直接用这个。
见:https://en.cppreference.com/w/cpp/string/char_traits/length
Special handling for nullptr
这个重载的注释写明了如果 str
可能是 nullptr
,则使用 absl::NullSafeStringView(str)
。
1 | // NullSafeStringView() |
猜测是获取 c-style 字符串长度的函数都已经默认参数是 non-null,例如 strlen()
。
C++ 23 会引入一个专门被标记为 deleted 的重载来避免可能存在的意外:
1 | constexpr basic_string_view(std::nullptr_t) = delete; // since C++ 23 |
std::string → string_view
abseil 的做法是 string_view 提供一个接受 std::basic_string<>
的重载
1 | template <typename Allocator> |
这个算是比较符合直觉的做法。
💡 这个 ctor 是 implicit 的
How about STL
C++ 标准库的做法就比较“另类”了:它选择为 std::string 提供一个 implicit operator std::basic_string_view()
。
string_view → std::string
abseil 的做法是提供一个 explicit std::basic_string<> operator
:
1 | // Explicit conversion operators |
How about STL
这部分同样是实现在 std::basic_string
中:
1 | template < class T > |
此处会针对 T
做 string_view 做 type-trait assert
不管是哪种实现,从 string_view → string 都是显式完成的,因为需要重新分配内存拷贝内容。
find_*_of 的查找优化
abseil::string_view 在实现这部分函数时,对于要检查的字符序列超过一个字符时,会在内部使用 lookup-table 来加速,使得这部分函数的复杂度从标准的 $O(size()*v.size())$ 提升到 $O(size())$。
对于长字符序列有一定的优化效果
1 | class LookupTable { |