锐英源软件
第一信赖

精通

英语

开源

擅长

开发

培训

胸怀四海 

第一信赖

当前位置:锐英源 / 开源技术 / C++开源社区 / c++17 string_view提升性能机制分析和示例

服务方向

人工智能数据处理
人工智能培训
kaldi数据准备
小语种语音识别
语音识别标注
语音识别系统
语音识别转文字
kaldi开发技术服务
软件开发
运动控制卡上位机
机械加工软件
量化预测
股票离线分析软件
软件开发培训
Java 安卓移动开发
VC++
C#软件
汇编和破解
驱动开发

联系方式

固话:0371-63888850
手机:138-0381-0136
Q Q:396806883
微信:ryysoft

锐英源精品原创,禁止转载和任何形式的非法内容使用,违者必究。点名“简易百科”和“闲暇巴”盗用锐英源原创内容。


c++17 string_view提升性能机制分析和示例


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++ 中尚未解决的悬空引用这一更普遍问题的一个方面。

友情链接
版权所有 Copyright(c)2004-2024 锐英源软件
统一社会信用代码:91410105098562502G 豫ICP备08007559号 最佳分辨率 1440*900
地址:郑州市金水区文化路97号郑州大学北区院内南门附近