精通
英语
和
开源
,
擅长
开发
与
培训
,
胸怀四海
第一信赖
服务方向
联系方式
锐英源精品原创,禁止转载和任何形式的非法内容使用,违者必究。点名“简易百科”和“闲暇巴”盗用锐英源原创内容。
C++17 为我们带来了一个名为 std::string_view 的新类型,该类型在string_view头文件中定义,已添加到标准库中。
由于此类型的性能,建议使用它来代替const std::string&输入字符串参数。这种类型的值将类似于 const std::string类型的值,但有一个主要区别:它们封装的字符串永远不能通过其公共接口进行修改。换句话说,std::string_view使我们能够以非拥有的方式引用现有字符串,我们可以查看但不能触摸std::string_view字符(虽然使用 const std::string_view& 没有错,但我们也可以按值传递std::string_view,因为复制这些对象很便宜)。
让我们看一下以下示例:
C++
#include <iostream>
#include <string_view>
#include <chrono>
void func_str(const std::string & s) {
std::cout << "s =" << s.data() << std::endl;
}
void func_str_view(std::string_view s) {
std::cout << "s =" << s.data() << std::endl;
}
int main() {
std::string str ("abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
auto t1 = std::chrono::high_resolution_clock::now();
func_str(str);
auto t2 = std::chrono::high_resolution_clock::now();
auto duration1 = std::chrono::duration_cast<std::chrono::milliseconds>(t2 - t1).count();
std::cout << "The processing time of func_str(str) is " << duration1 << " ticks\n\n";
auto t3 = std::chrono::high_resolution_clock::now();
func_str_view(str);
auto t4 = std::chrono::high_resolution_clock::now();
auto duration2 = std::chrono::duration_cast<std::chrono::milliseconds>(t4 - t3).count();
std::cout << "The processing time of func_str_view(str) is " << duration2 << " ticks\n\n";
return 0;
}
当然,在您的机器上,输出可能会有所不同,但无论如何,上面的示例表明使用std::string_view函数要快得多。请注意,func_str_view函数接受一些 string,但不需要所有权,它清楚地反映了意图:该函数获得了string视图 .该func_str_view函数也可以使用const char *参数,因为 std::string_view是字符数组的薄视图,只包含一个指针和一个长度。因此,这允许我们只提供一种方法,它可以有效地获取const char*或std::string , 而不会不必要地复制底层数组。
例如,我们可以这样调用函数:
C++
func_str_view("abcdefghijklmnopqrstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ");
这个func_str_view函数不拥有任何东西,它只查看string 并且不涉及任何堆分配和字符数组的深度复制。堆分配里的工作是函数参数对象,深度复制是指参数对象构造函数里的工作。如果大家不明白这个道理,可以自己写一些类似string的代码来实验下,看STL容器概念下,数据在对象里,进行遍历或函数调用返回时,对构造函数的调用情况,每次调用都要涉及堆对象的分配,后续要释放,这些分配和释放都需要占用CPU和内存。
这就是为什么这个函数的运行速度比 快得多的原因。func_str
同时,std::string_view与它"kinsman" -std::string相比,它也有许多局限性:
std::string_view对 null 终止一无所知
与 std::string不同,std::string_view不支持该c_str ()函数,该函数会给我们一个带有null -terminated 的字符数组。当然,std::string_view具有data()函数,但与std::string的data()一样,这并不能保证字符数组将以 null-terminated 终止。
因此,要调用带有string null -terminated 参数的函数:
func_str_view_c_str("aaaaabbbbbccccc");
我们需要在函数体中创建一个临时string std::string对象,例如,像这样:
C++
void func_str_view_c_str(std::string_view s) {
std::cout << "s = " << std::string(s).c_str()
<< std::endl; // string_view does not provide a c_str()
}
从函数返回std::string_view可能会导致指针悬空的问题:
让我们看一下以下示例:
#include <iostream>
#include <string_view>
class StringMngr {
std::string m_str;
public:
StringMngr(const char* pstr = "Test") :m_str(pstr) {}
std::string_view GetSubString() const {
return m_str.substr(1u); // substring starts at index 1 till the end
}
};
int main() {
StringMngr str_mgr;
std::cout << "str_mgr.GetSubString() = " << str_mgr.GetSubString();
return 0;
}
上述代码是如何工作的?可能是什么问题?
我们只是想赋予substring审查 的权利,但问题是std::string::substr()返回一个 std::string类型的临时对象。
该方法返回时间线的概览(即视图),当概览可以使用时,该概览将消失。
正确的解决方案是在调用 substr之前显式转换为std::string_view :
C++std::string_view GetSubString() const {
return std::string_view(m_str).substr(1u);
}
修改GetSubString()函数后,我们得到预期的输出:
Substring
std::string_view的substr()方法更正确:它返回子字符串的概述,而不创建临时副本。
真正的问题是,理想情况下,该.std::string::substr()方法应返回std::string_view
这只是 C++ 中尚未解决的悬空引用这一更普遍问题的一个方面。