C++相当于 StringBuffer/StringBuilder?
是否有一个 C++ 标准模板库类可以提供高效的字符串连接功能,类似于 C# 的 StringBuilder 或 Java 的 StringBuffer ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
是否有一个 C++ 标准模板库类可以提供高效的字符串连接功能,类似于 C# 的 StringBuilder 或 Java 的 StringBuffer ?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(11)
C++ 方法是使用 std::stringstream 或只是简单的字符串连接。 C++ 字符串是可变的,因此连接的性能考虑不太重要。
关于格式化,您可以对流进行所有相同的格式化,但以不同的方式,类似于
cout
。或者您可以使用强类型函子来封装它并提供类似 String.Format 的接口,例如 boost::formatThe C++ way would be to use std::stringstream or just plain string concatenations. C++ strings are mutable so the performance considerations of concatenation are less of a concern.
with regards to formatting, you can do all the same formatting on a stream, but in a different way, similar to
cout
. or you can use a strongly typed functor which encapsulates this and provides a String.Format like interface e.g. boost::formatstd::string.append
函数不是一个好的选择,因为它不接受多种形式的数据。更有用的替代方法是使用 std::stringstream ;像这样:The
std::string.append
function isn't a good option because it doesn't accept many forms of data. A more useful alternative is to usestd::stringstream
; like so:注意这个答案最近受到了一些关注。我并不提倡将此作为解决方案(这是我过去在 STL 之前见过的解决方案)。这是一种有趣的方法,只有在对代码进行分析后发现这会有所改进时,才应应用于
std::string
或std::stringstream
。我通常使用
std::string
或 < a href="http://en.cppreference.com/w/cpp/io/basic_stringstream" rel="noreferrer">std::stringstream
。我从来没有遇到过这些问题。如果我提前知道绳子的粗略尺寸,我通常会先保留一些房间。我在很久以前就见过其他人制作自己的优化字符串生成器。
它使用两个字符串,一个用于字符串的大部分,另一个作为用于连接短字符串的暂存区域。它通过在一个小字符串中批处理短追加操作然后将其追加到主字符串来优化追加,从而减少主字符串变大时所需的重新分配次数。
我不需要使用
std::string
或std::stringstream
使用此技巧。我认为它是在 std::string 之前与第三方字符串库一起使用的,那是很久以前的事了。如果您采用这样的策略,首先要分析您的应用程序。NOTE this answer has received some attention recently. I am not advocating this as a solution (it is a solution I have seen in the past, before the STL). It is an interesting approach and should only be applied over
std::string
orstd::stringstream
if after profiling your code you discover this makes an improvement.I normally use either
std::string
orstd::stringstream
. I have never had any problems with these. I would normally reserve some room first if I know the rough size of the string in advance.I have seen other people make their own optimized string builder in the distant past.
It uses two strings one for the majority of the string and the other as a scratch area for concatenating short strings. It optimise's appends by batching the short append operations in one small string then appending this to the main string, thus reducing the number of reallocations required on the main string as it gets larger.
I have not required this trick with
std::string
orstd::stringstream
. I think it was used with a third party string library before std::string, it was that long ago. If you adopt a strategy like this profile your application first.std::string
是 C++ 的等价物:它是可变的。std::string
is the C++ equivalent: It's mutable.您可以使用 .append() 来简单地连接字符串。
我想你甚至可以这样做:
至于C#的
StringBuilder
的格式化操作,我相信snprintf
(或者sprintf
如果你想将错误代码写入字符数组并转换回字符串的风险是唯一的选择。You can use .append() for simply concatenating strings.
I think you might even be able to do:
As for the formatting operations of C#'s
StringBuilder
, I believesnprintf
(orsprintf
if you want to risk writing buggy code ;-) ) into a character array and convert back to a string is about the only option.由于 C++ 中的 std::string 是可变的,因此您可以使用它。它有一个
+=运算符
和一个append
函数。如果您需要附加数字数据,请使用
std::to_string
函数。如果您希望能够将任何对象序列化为字符串,从而获得更大的灵活性,请使用 std::stringstream 类。但是您需要实现自己的流运算符函数,才能使其与您自己的自定义类一起使用。
Since
std::string
in C++ is mutable you can use that. It has a+= operator
and anappend
function.If you need to append numerical data use the
std::to_string
functions.If you want even more flexibility in the form of being able to serialise any object to a string then use the
std::stringstream
class. But you'll need to implement your own streaming operator functions for it to work with your own custom classes.C++ 的便捷字符串生成器
就像许多人之前回答的那样,std::stringstream 是首选方法。
它运行良好,并且有很多转换和格式选项。在我看来,它有一个非常不方便的缺陷:你不能将它用作单行或表达式。
你总是必须写:
这非常烦人,特别是当你想在构造函数中初始化字符串时。
原因是,a) std::stringstream 没有到 std::string 的转换运算符,b) 运算符 << stringstream 的 () 不返回 stringstream 引用,而是返回 std::ostream 引用 - 无法将其进一步计算为字符串流。
解决方案是重写 std::stringstream 并为其提供更好的匹配运算符:
这样,您就可以
在构造函数中编写甚至这样的内容。
我必须承认我没有测量性能,因为我还没有在大量使用字符串构建的环境中使用它,但我认为它不会比 std::stringstream 差多少,因为一切都完成了通过引用(除了转换为字符串,但这也是 std::stringstream 中的复制操作)
A convenient string builder for c++
Like many people answered before, std::stringstream is the method of choice.
It works good and has a lot of conversion and formatting options. IMO it has one pretty inconvenient flaw though: You can not use it as a one liner or as an expression.
You always have to write:
which is pretty annoying, especially when you want to initialize strings in the constructor.
The reason is, that a) std::stringstream has no conversion operator to std::string and b) the operator << ()'s of the stringstream don't return a stringstream reference, but a std::ostream reference instead - which can not be further computed as a string stream.
The solution is to override std::stringstream and to give it better matching operators:
With this, you can write things like
even in the constructor.
I have to confess I didn't measure the performance, since I have not used it in an environment which makes heavy use of string building yet, but I assume it won't be much worse than std::stringstream, since everything is done via references (except the conversion to string, but thats a copy operation in std::stringstream as well)
std::string 的 += 不适用于 const char* (类似于“要添加的字符串”之类的东西),因此使用 stringstream 绝对是最接近所需的 - 您只需使用 <<而不是 +
std::string's += doesn't work with const char* (what stuff like "string to add" appear to be), so definitely using stringstream is the closest to what is required - you just use << instead of +
如果必须在随机位置插入/删除字符串,则 Rope 容器可能是值得的目标字符串或长字符序列。
下面是 SGI 实现的一个示例:
The Rope container may be worth if have to insert/delete string into the random place of destination string or for a long char sequences.
Here is an example from SGI's implementation:
我想添加一些新的东西,因为以下原因:
第一次尝试时,我未能击败
std::ostringstream
的operator<<
效率,但随着更多的尝试,我能够制作出在某些情况下更快的 StringBuilder。
每次我附加一个字符串时,我只是在某处存储对它的引用并增加总大小的计数器。
我最终实现它的真正方法(恐怖!)是使用不透明缓冲区(std::vector < char >):
对于字节 []
对于移动的字符串(附加有
std::move
)std::string
对象(我们拥有所有权)的指针会在类中设置一个标志 /em>
std::string
对象的指针(无所有权)还有一个小的优化,如果最后插入的字符串被移动,它会检查空闲保留但未使用的字节并进一步存储那里的字节而不是使用不透明缓冲区(这是为了节省一些内存,它实际上使它稍微慢一些,可能还取决于CPU,并且无论如何都很少看到带有额外保留空间的字符串)
这最终比
std::ostringstream
但它有一些缺点:ostringstream
的所有功能结论?使用
std::ostringstream
它已经解决了最大的瓶颈,同时通过我的实现提高了几个百分点的速度,这是不值得的。
I wanted to add something new because of the following:
At a first attemp I failed to beat
std::ostringstream
'soperator<<
efficiency, but with more attemps I was able to make a StringBuilder that is faster in some cases.
Everytime I append a string I just store a reference to it somewhere and increase the counter of the total size.
The real way I finally implemented it (Horror!) is to use a opaque buffer(std::vector < char > ):
for byte [ ]
for moved strings (strings appended with
std::move
)std::string
object (we have ownership)for strings
std::string
object (no ownership)There's also one small optimization, if last inserted string was mov'd in, it checks for free reserved but unused bytes and store further bytes in there instead of using the opaque buffer (this is to save some memory, it actually make it slightly slower, maybe depend also on the CPU, and it is rare to see strings with extra reserved space anyway)
This was finally slightly faster than
std::ostringstream
but it has few downsides:ostringstream
conclusion? use
std::ostringstream
It already fix the biggest bottleneck while ganing few % points in speed with mine implementation is not worth the downsides.
常规 std::string 相当于 Java 中的 StringBuffer,因为它是可变的。如果我简化很多,Java 字符串就像不可变的全局常量,这会导致每次需要更改时都会创建新对象。相比之下,StringBuffer(和 std::string)相当于动态字符数组。附加到它上的是 O*(1)。追加的最坏情况是 O(n),但 k 次连续调用追加会导致 kO(1) 次操作 => O*(1)。
详细了解插入动态数组的摊销复杂度分析。
Regular std::string is the equivalent to StringBuffer in Java as it is mutable. If I simplify a lot, Java strings are something like immutable global constants which causes creating new objects everytime they have to change. In contrast StringBuffer (and std::string) is the equivalent of a dynamic array of chars. Appending to it is O*(1). Worst case of append is O(n) but k consecutive calls to append lead to k.O(1) operations => O*(1).
Read more about amortized complexity analysisof insertion into dynamic array.