std::string_view 简要介绍
2022-02-15
3 min read
std::string_view 简要介绍
目的
字符串在开发中使用频率很高,其性能至关重要。C++ 标准库中的 std::string 采用多种技术以提升性能。比如:短字符串优化技术,当字符串较短时,直接在栈上分配空间,不进行动态内存分配,从而提升短字符串的效率;
但是字符串的初始化会影响其性能。std::string 一般通过 char* 类型进行初始化,例如:字符串字面量、从文件读入等,这样就需将 char* 字符数据拷贝到 std::string 所管理的内存空间中;而很多时候并不会去修改字符串内容,拷贝毫无必要,仅需生成 char* 某种标记即可,所以此时 std::string 初始化就造成了性能损失;
针对上述问题,C++17 引入了 std::string_view 。std::string_view 仅标记字符串位置与尺寸,不拷贝字符串数据,避免了额外的内存分配。所以当仅访问而不修改字符串时,std::string_view 即可提升效率;
对比
下述代码对 std::string 与 std::string_view 的性能进行了简单对比。需要注意的是,测试字符串的长度需超过 std::string 开启短字符串优化的长度,这样差别更为显著;
#include <iostream>
#include <vector>
#include <string>
#include <string_view>
#include <chrono>
/**
* @brief std::string 与 std::string_view 测试
*/
int main()
{
const int N = 1000000;
const char s[] = "qwertyuiopasdfghjklzxcvbnm1234567890"; // 使用 GCC 编译,长度需超过 23
auto start = std::chrono::system_clock::now();
for (int i = 0; i < N; ++i) {
std::string str = s;
std::string sub = str.substr(2, 10);
}
auto end = std::chrono::system_clock::now();
auto elapse = (std::chrono::duration_cast<std::chrono::milliseconds>(end-start)).count();
std::cout << "string type elapse: " << elapse << " ms \n";
start = std::chrono::system_clock::now();
for (int i = 0; i < N; ++i) {
std::string_view str = s;
std::string_view sub = str.substr(2, 10);
}
end = std::chrono::system_clock::now();
elapse = (std::chrono::duration_cast<std::chrono::milliseconds>(end-start)).count();
std::cout << "string_view type elapse: " << elapse << " ms \n";
return 0;
}
终端输出:
string type elapse: 4111 ms
string_view type elapse: 8 ms
从上述代码看出,使用 std::string_view 后,循环中的操作性能提升约 500 倍,几乎是质的飞跃;
总结
在处理字符串时,当仅需访问而不修改其内容时,可多使用 std::string_view 代替 std::string,以消除数据拷贝,避免额外内存分配,进而提升处理字符串的效率;
参考
版权声明:
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明出处!