C++ 中的高效字符串连接

问题描述:

我听到一些人对 std::string 中的+"运算符和各种加速连接的解决方法表示担忧.这些真的有必要吗?如果是这样,在 C++ 中连接字符串的最佳方法是什么?

I heard a few people expressing worries about "+" operator in std::string and various workarounds to speed up concatenation. Are any of these really necessary? If so, what is the best way to concatenate strings in C++?

额外的工作可能不值得,除非你真的很需要效率.你可能会因为使用运算符 += 代替.

The extra work is probably not worth it, unless you really really need efficiency. You probably will have much better efficiency simply by using operator += instead.

现在在免责声明之后,我将回答您的实际问题......

Now after that disclaimer, I will answer your actual question...

STL 字符串类的效率取决于您使用的 STL 实现.

The efficiency of the STL string class depends on the implementation of STL you are using.

您可以保证效率更好地控制自己通过c内置函数手动进行连接.

You could guarantee efficiency and have greater control yourself by doing concatenation manually via c built-in functions.

为什么 operator+ 效率不高:

看看这个界面:

template <class charT, class traits, class Alloc>
basic_string<charT, traits, Alloc>
operator+(const basic_string<charT, traits, Alloc>& s1,
          const basic_string<charT, traits, Alloc>& s2)

可以看到在每个+之后返回了一个新对象.这意味着每次都使用一个新的缓冲区.如果您正在执行大量额外的 + 操作,则效率不高.

You can see that a new object is returned after each +. That means that a new buffer is used each time. If you are doing a ton of extra + operations it is not efficient.

为什么可以提高效率:

  • 您是在保证效率,而不是相信代理人会为您高效地完成工作
  • std::string 类对字符串的最大大小一无所知,也不知道连接它的频率.您可能拥有这些知识,并且可以根据这些信息做事.这将导致更少的重新分配.
  • 您将手动控制缓冲区,以便确保在您不希望发生这种情况时不会将整个字符串复制到新缓冲区中.
  • 您可以将堆栈用于缓冲​​区而不是堆,这样效率更高.
  • string + 运算符将创建一个新的字符串对象并使用新的缓冲区返回它.

实施注意事项:

  • 跟踪字符串长度.
  • 保留一个指向字符串结尾和开头的指针,或者只是开头并使用开头 + 长度作为偏移量来查找字符串的结尾.
  • 确保您存储字符串的缓冲区足够大,这样您就不需要重新分配数据
  • 使用 strcpy 而不是 strcat,因此您无需遍历字符串的长度即可找到字符串的结尾.

绳索数据结构:

如果您需要非常快速的连接,请考虑使用 绳索数据结构.

If you need really fast concatenations consider using a rope data structure.