时间:2021-05-20
C++中std::string是日常Coding中经常使用的一个类,使用起来非常方便,但是也存在一些弊端。
如下代码,参数传递的过程发生了内存分配(Memory Allocation)和内存拷贝。
void fun(const std::string& s) { std::cout << s << std::endl;}const char* ch = "hello world";// bad way, expensive if the string is longfun(ch);再看下面的常用的字符串截取实现:
// very long stringstd::string str = "lllloooonnnngggg sssstttrrriiinnnggg"; // bad way, expensive if the string is longstd::cout << str.substr(15, 10) << '\n';为了进一步的压榨程序的性能,需要移除掉这些昂贵的字符串内存分配和拷贝操作。C++17中提供了std::string_view可以帮助我们实现这一功能,该类并不持有字符串的拷贝,而是与源字符串共享其内存空间。
string_view构造函数
constexpr basic_string_view() noexcept; (since C++17)constexpr basic_string_view(const basic_string_view& other) noexcept = default; (since C++17)constexpr basic_string_view(const CharT* s, size_type count);(since C++17)constexpr basic_string_view(const CharT* s); (since C++17)template<class It, class End>虽然没有定义参数为std::string的std::string_view函数,下面的代码仍然可以通过编译。
std::string str("hello string view!");std::string_view sview(str);因为std::string类重载了std::string到std::string_view的转换操作符。
operator basic_string_view<charT, traits>() const noexcept;std::string_view避免内存拷贝
有了string_view,我们就可以很好的解决文章开头提到的问题。
void fun(const std::string_view& s) { std::cout << s << std::endl;}const char* ch = "hello world, char";fun(ch); const std::string str = "hello world, string";fun(str);fun({ch, 5});有了std::string_view,函数参数不管是字符串数组指针,还是std::string,都不需要拷贝内存源字符串。
// very long stringstd::string str = "lllloooonnnngggg sssstttrrriiinnnggg";//Good way - No copies are created!std::string_view view = str;// string_view::substr returns a new string_viewstd::cout << view.substr(15, 10) << '\n';同理,字符串的substr()函数也不需要再进行拷贝了,这对于非常长的字符串,可以有效的提升程序的性能表现。
std::string_view注意事项
由于std::string_view并不持有字符串的内存,所以它的生命周期一定要比源字符串的生命周期长。一些典型的生命周期管理错误的例子:
std::string_view sv = std::string("hello world");std::string_view fun() { std::string str("hello world"); return std::string_view(str);}std::string_view的结尾并没有\0结束符,所以在输出std::string_view的时候要注意边界,如下代码:
#include <iostream>#include <vector>#include <string>#include <string_view>int main() { const char* ch = "hello world"; std::string_view sv(ch, 2); std::cout << sv << std::endl; std::cout << sv.data() << std::endl; return 0;}程序输出:
hehello worldstd::cout << sv.data() << std::endl; 这行代码输出了hello world,这是因为sv仍然指向源字符串内存,调用sv.data()打印时,仍然沿用了C++对于字符串的约定,直到遇到结束符\0时,打印才结束,这时候就输出了完整的源字符串内容。当然这里明显是不符合预期的,尤其是std::string_view指向的字符串没有\0结束符的时候,程序很容易出现潜在的内存问题。所以此处一定要小心。
参考材料
https://riptutorial.com/cplusplus/example/6571/using-the-std–string-view-class
https://en.cppreference.com/w/cpp/string/basic_string_view
https://segmentfault.com/a/1190000018387368
以上就是C++17 使用 std::string_view避免字符串拷贝优化程序性能的详细内容,更多关于c++17 std::string_view的资料请关注其它相关文章!
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
String类可以说是Java编程中使用最多的类了,如果能对String字符串的性能进行优化,那么程序的性能必然能大幅提升。这不JDK9就对String字符串进
最大的区别就是C风格的字符串是静态的,不可以动态变化,使用极为麻烦。而C++的std::string类型动态管理,非常方便。C风格字符串和char数组是不一样的
C语言实现字符串操作函数的实例在编写程序的过程中,我们经常使用到一些字符串函数,例如求字符串长度,拷贝字符串……,这些函数都在C标准库中存在,我们可以直接使用。
简介QString字符串被每个GUI程序所使用,不仅是用户界面,还有数据结构。C++原生提供两种字符串:传统的C风格以'\0'结尾的字符数组和std::stri
regex库中涉及到的主要类型有:以std::string为代表的处理字符串的类型(我们知道还有存储wchar_t的wstring类、原生c式字符串constc