string_view : {data_pointer , data_len}
不拥有数据、只读
解决在只需读str时 还会拷贝str造成的开销 ; 提高效率.
可用string_view代替const string &作为形参
总结如下
string_view
原因
- 为什么要有string_view ? 提高性能. 为什么提高性能 ? 有const string &还不够吗 ?
- const string &问题如下.
- 对于形参为const string&的,此时的情况必然是传递的数据为只读.
- 使用&当然是为了避免拷贝, 可是对于要传递给const & , 只有当实参类型相同 , 即为string时, 才不会发生拷贝.
- 如果实参 字符串字面值(“sss”)、字符数组(char [])、字符串指针(char *) 的传递给 const string& —> 仍要数据拷贝
- 实参与string类型不同 , 则需要拷贝生成个string临时对象,然后const string &指向这个临时对象. 见(C++ Primer)
- 同时string的substr效率为O(n),耗费性能.
- O(n) : 因为substr会生成新的子串
- 我们本意很可能并不是要改变原字符串,实际上返回源字符串本身的一部分即可
特点
- string_view
- 组成 : {data_pointer , data_len}.
- string_view本身并不持有数据,只是有个指向数据的指针罢了. 所以注意string_view可能指向一个已经失效的str
- 只读data,不可修改data
- 构造:除默认构造和拷贝构造外,还有
- constexpr string_view(const CharT* s, size_type count);
- constexpr string_view(const CharT* s);
- string_view foo(string(“abc”))
- a. string(“abc”)转换为string_view对象
- b. string_view对象拷贝构造
- 自定义字面量 : sv做后缀 , 将串中的\0视作字符而非null
1
2
3
4
5
6
7using namespace std::literals;
std::string_view s1 = "abc\0\0def";
std::string_view s2 = "abc\0\0def"sv;
std::cout << "s1: " << s1.size() << " \"" << s1 << "\"\n";
std::cout << "s2: " << s2.size() << " \"" << s2 << "\"\n";
s1: 3 "abc"
s2: 8 "abc^@^@def" - 好处
- 我们可以使用string_view 代替 const string & 作为形参. 效率更高. 无论实参是 “sss” , char[] , 还是 char * , 还是string , 都只需要构造一个string_view , 然后拷贝构造string_view即可. 代价基本仅仅是1 data_pointer + 1 data_len. 远小于拷贝整个string的代价.
- string_view的substr函数的时间复杂度是O(1).(移动data_pointer构造string_view即可)
- 注意
- string_view范围内的字符可能不包含\0
- 从[const] char*构造string_view对象时间复杂度O(n).(为了遍历获取data_len)
- string_view指向的内容的生命周期可能比其本身短
- 指导 : 约束少,使用自由,难以保证data的生命周期长于string_view. 故我们应将string_view作为函数形参,因为如果该参数仅仅在函数体内使用而不传递出去,这样使用是安全的。
- 当然string_view作为函数形参 , 整个函数中 绝对不会出现data失效的问题.
- 不过可以看到 cs144中依然返回了string_view(Buffer.h) ,因为Buffer内部通过shared_ptr保证了data的生命周期 ?