c/c++语言开发共享C++17 使用 std::string_view避免字符串拷贝优化程序性能

c++中std::string是日常coding中经常使用的一个类,使用起来非常方便,但是也存在一些弊端。如下代码,参数传递的过程发生了内存分配(memory allocation)和内存拷贝。voi

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 long  fun(ch); 

再看下面的常用的字符串截取实现:

  // very long string  std::string str = "lllloooonnnngggg sssstttrrriiinnnggg";     // bad way, expensive if the string is long  std::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 string  std::string str = "lllloooonnnngggg sssstttrrriiinnnggg";    //good way - no copies are created!  std::string_view view = str;    // string_view::substr returns a new string_view  std::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的结尾并没有结束符,所以在输出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;  }

程序输出:

  he  hello world

std::cout << sv.data() << std::endl; 这行代码输出了hello world,这是因为sv仍然指向源字符串内存,调用sv.data()打印时,仍然沿用了c++对于字符串的约定,直到遇到结束符时,打印才结束,这时候就输出了完整的源字符串内容。当然这里明显是不符合预期的,尤其是std::string_view指向的字符串没有结束符的时候,程序很容易出现潜在的内存问题。所以此处一定要小心。

参考材料

以上就是c++17 使用 std::string_view避免字符串拷贝优化程序性能的详细内容,更多关于c++17 std::string_view的资料请关注<计算机技术网(www.ctvol.com)!!>其它相关文章!

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/c-cdevelopment/597254.html

(0)
上一篇 2021年5月8日
下一篇 2021年5月8日

精彩推荐