0
点赞
收藏
分享

微信扫一扫

[c++实践]关于标准库中字符串的高效处理

[c++实践]关于标准库中字符串的高效处理

无论什么程序,都需要大量的使用字符串,c++标准库提供了 std::string 对字符串进行处理。熟悉 std::string 实现逻辑的都知道,std::string 库比较耗时的操作主要在内存的分配与字符串的拼接。因为内存分配实际上还是使用的 malloc ,但是在多线程环境下调用该函数会有一个全局的锁,如果频繁的调用该函数会导致性能的严重下降。而字符串拼接的性能底下则归咎于 std::string 库实现的原理。比如如下代码:

std::string log_path = log_dir + "/" + log_name + ".log";

这短短的一段代码,缺构造了多个临时变量,这主要是由 std::string::operator+ 操作会构造新对象引起的,以下为gcc9.4.0版本中的实现:

  template<typename _CharT, typename _Traits, typename _Alloc>
    basic_string<_CharT, _Traits, _Alloc>
    operator+(const basic_string<_CharT, _Traits, _Alloc>& __lhs,
	      const basic_string<_CharT, _Traits, _Alloc>& __rhs)
    {
      basic_string<_CharT, _Traits, _Alloc> __str(__lhs);
      __str.append(__rhs);
      return __str;
    }

可以看到虽然它返回的是一个 basic_string 对象而非引用,因此每+一次都会够早一个临时变量,而构造一个std::string会调用std::string::operator(const std::string &并在内部重新分配内存,然后进行内存拷贝。

从上面可以知道,只要消除临时变量的创建以及减少内存的分配就可以提高std::string拼接字符串的效率。我们可以先使用 std::string::reserve 一次分配足够的内存,然后使用 std::string::operator+=std::string::append 代替上面的 std::string::operator+,因为他们返回的是对象的引用,不会构造临时对象。

除了字符串的拼接,有时候还需要传递字符串,比如作为参数传递或者作为结果返回。我们可以使用引用作为参数传递以减少对象的拷贝,而当std::string作为返回值时我们可以使用std::move将它转换为右值(实际上不需要我们显示的进行,因为编译器在优化的时候会做的比std::move更好,可以见关于右值引用的讨论)。

更进一步的,如果使用c++17,则可以使用新引入的 std::string_view ,这里不做介绍,因为我们的工程使用的是 c++11标准。

举报

相关推荐

0 条评论