一、背景
这篇文章从性能与工程可用性两条线出发,讲清了为什么 std::string_view 是现代 C++ 中值得优先考虑的只读字符串接口。背景问题传统 const std::string& 在接收字面量、字符数组、字符指针时可能触发隐式构造与拷贝。std::string::substr 返回新字符串,常引入额外分配与复制成…
一、背景 在日常C/C++编程中,我们常进行数据的传递操作,比如,将数据传给函数。当数据占用的内存较大时,减少数据的拷贝可以有效提高程序的性能。在C中指针是完成这一目的的标准数据结构,而C++引入了安全性更高的引用类型。所以在C++中若传递的数据仅仅只读,const string&成了C++**的天然的方式。但这并非完美,从实践来看,它至少有以下几方面问题:字符串字面值、字符数组、字符串指针的传递仍要数据拷贝 这三类低级数据类型与string类型不同,传入时,编译器需要做隐式转换,即需要拷贝这些数据生成string临时对象。const string&指向的实际上是这个临时对象。通常字符串字面值较小,性能损耗可以忽略不计;但字符串指针和字符数组某些情况下可能会比较大(比如读取文件的内容),此时会引起频繁的内存分配和数据拷贝,会严重影响程序的性能。substr O(n) 复杂度 这是一个特别常用的函数,好在std::string提供了这个函数,美中不足的是其每次都返回一个新生成的子串,很容易引起性能热点。实际上我们本意并不是要改变原字符串,为什么不在原字符串基础上返回呢? 在C++17中引入了string_view,能很好的解决以上两个问题。二、std::string_view 从名字出发,我们可以类比数据库视图,view表示该类型不会为数据分配存储空间,而且该数据类型只能用来读。该数据类型可通过{数据的起始指针,数据的长度}两个元素表示,实际上该数据类型的实例不会具体存储原数据,仅仅存储指向的数据的起始指针和长度,所以这个开销是非常小的。 要使用字符串视图,需要引入<string_view>,下面介绍该数据类型主要的API。这些API基本上都有constexpr修饰,所以能在编译时很好地处理字符串字面值,从而提高程序效率。2.1 构造函数constexpr string_view() noexcept; constexpr string_view(const string_view& other) noexcept = default; constexpr string_view(const CharT* s, size_type count); constexpr string_view(const CharT* s); 唯一需要说明的是:为什么我们代码string_view foo(string("abc"))可以编译通过,但为什么没有对应的构造函数? 实际上这是因为string类重载了string到string_view的转换操作符: operator std::basic_string_view<CharT, Traits>() const noexcept;2.2 自定义字面量 自定义字面量也是C++17新增的特性,提高了常量的易读。 下面的代码取值cppreference,能很好地说明自定义字面值和字符串语义的差异。#include <string_view> #include <iostream> int main() { using 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" 以上例子能很好看清二者的语义区别,\0对于字符串而言,有其特殊的意义,即表示字符串的结束,字符串视图根本不care,它关心实际的字符个数。2.3 成员函数 下面列举其成员函数:忽略了函数的返回值,若函数有重载,括号内用...填充。这样可以对其有个整体轮廓。// 迭代器 begin() end() cbegin() cend() rbegin() rend() crbegin() crend() // 容量 size() length() max_size() empty() // 元素访问 operator[](size_type pos) at(size_type pos) front() back() data() // 修改器 remove_prefix(size_type n) remove_suffix(size_type n) swap(basic_string_view& s) copy(charT* s, size_type n, size_type pos = 0) s…
正在初始化 WebAssembly 引擎…
首次编译原生模块可能需要数秒
就绪后,页面交互将以接近原生的速度运行