C++17中引入一种轻量级的字符串视图类型std::string_view。它
内部只保存一个指针和长度,避免了字符串的深拷贝,提高了处理效率。
1 比较C-style,std::string和std::string_view
比较C风格字符串,std::string和std::string_view对内存空间的占用,示例如下:
#include <iostream>
#include <string>
#include <string_view>
int main()
{
const char* cstr = "Hello world! I am Beijing";
std::string str = "Hello world! I am Beijing";
std::string_view stringView(str);
std::cout << "cstr: " << sizeof(cstr) << std::endl;
std::cout << "str: " << sizeof(str) << std::endl;
std::cout << "stringView: " << sizeof(stringView) << std::endl;
}
运行结果:
cstr: 8
str: 40
stringView: 16
注:(1)sizeof(cstr) 返回的是指针本身在内存中占用的字节数。我的机器是64位系统,指针通常占用8个字节,因此返回8。
(2)sizeof(str) 返回对象 str
在内存中占用的字节数。它通常包含一个指针(指向字符串的数据);一个整数(存储字符串的长度);一个整数(存储字符串的容量);额外的管理数据(某些实现中有引用计数等)。
(3)sizeof(stringView)返回字符串视图类型的在内存中占用的字节数。它通常包含一个指针和长度。我的机器是64位系统,指针通常占用8个字节,整型长度通常占用8个字节,因此返回16。
2 std::string_view
作为函数参数
std::string_view经常作为函数的参数传递字符串。此时std::string_view是只读的,不允许修改参数值。
#include <iostream>
#include <string>
#include <string_view>
#include <cstring>
using namespace std;
string cat(string_view sv1, string_view sv2)
{
string res;
res.resize(sv1.length()+sv2.length());
copy(sv1.begin(), sv1.end(), res.begin());
copy(sv2.begin(), sv2.end(), res.begin() + sv1.length());
return res;
}
int main()
{
string king = "Harold";
auto s1 = cat(king, "William"); // string and const char*
auto s2 = cat(king, king); // string and string
auto s3 = cat("Edward", "Stephen"sv); // const char * and string_view
auto s4 = cat("Canute"sv, king); // string_view and string
auto s5 = cat({&king[0],2},"Henry"sv);
std::cout << "s1: " << s1 << std::endl;
std::cout << "s2: " << s2 << std::endl;
std::cout << "s3: " << s3 << std::endl;
std::cout << "s4: " << s4 << std::endl;
std::cout << "s5: " << s5 << std::endl;
}
运行结果:
s1: HaroldWilliam
s2: HaroldHarold
s3: EdwardStephen
s4: CanuteHarold
s5: HaHenry
与使用const std::string&作为函数参数相比,使用std::string_view的优点是:
(1)可以混用多种类型的字符串(C风格字符串,std::string和std::string_view
)
(2)使用C风格字符串时,不需要生成临时的std::string对象。
(3)可以方便的传递子串。
3 std::string_view
作为函数返回值
std::string_view
作为函数返回值时,要特别注意避免指向局部变量。
string_view bad()
{
string s = "Once upon a time";
return {&s[5],4}; // bad: returning a pointer to a local
}
上述代码返回的 std::string_view指向函数中的局部变量s,s在函数结束后会被析构掉。此后使用string_view会产生错误行为。