我是C++字符串的新手。有没有办法一次连接两个以上的字符串?或者我必须在两个字符串连接?我担心的是,它可能需要为每个操作分配内存,而不是只为最终结果分配一次内存。一次Concat多个C++字符串?
在java中记住类似的东西,想知道std中是否有某种方法。实际上,std :: stringstream可能是它,但我不知道它是如何工作的。
我是C++字符串的新手。有没有办法一次连接两个以上的字符串?或者我必须在两个字符串连接?我担心的是,它可能需要为每个操作分配内存,而不是只为最终结果分配一次内存。一次Concat多个C++字符串?
在java中记住类似的东西,想知道std中是否有某种方法。实际上,std :: stringstream可能是它,但我不知道它是如何工作的。
是,以避免昂贵的浪费内存使用stringstream
的std :: stringstream的可能是的,但我不知道它的工作原理。
这是它如何工作的:包括sstream,创建一个对象,附加到它,就像你需要用流运算符< <得到的结果作为字符串调用函数STR
例如:
#include <sstream>
std::stringstream mySS;
mySS << "Hello" << " World!" << "end!!" << " Foo";
,当你完成
std::string stringResult = mySS.str();
因此,它实际上保持所有字符串,直到.str()调用?这是我想知道的。谢谢。 –
确切地说,你追加和追加的东西,直到你需要它,然后调用str()....或多或少像在Java中的StringBuilder .... –
对不起,有一个额外的问题,我不知道怎么才能真正检查它是否像那样工作。在调试器中打开它我猜? –
您可以在reserve
之前预先留出必要的空间,避免重新分配。
std::string s0{/*...*/}, s1{/*...*/}, s2{/*...*/};
std::string sink;
sink.reserve(s0.size() + s1.size() + s2.size() + 1);
sink += s0;
sink += s1;
sink += s2;
可以使这更好的了可变参数string_cat
功能。下面是一个C++ 17的实现:
template <typename... Strings>
std::string string_cat(Strings&&... strings)
{
std::string result;
result.reserve((strings.size() + ...) + 1);
((result += std::forward<Strings>(strings)), ...);
return result;
}
用法:
using namespace std::literals;
auto res = string_cat("a"s, "b"s, "c"s);
您可以连接多个字符串 - 没问题:
std::string hello = "Hello";
std::string cruel = "cruel";
std::string world = "world";
std::string result = hello + " " + cruel + " " + world;
结果result
持有字符串 “Hello残酷的世界”。
如果您使用的是C风格的字符串(即char*
),那么您可以分配一次并捕捉多次。 strcat
函数将指向目标地址的指针作为第一个参数。因此,如果你足够大的目标字符串,只会有一个分配。因此
char* dest = new char[100];
dest[0] = 0; //Zero length string to start
strcat(dest, str1);
strcat(dest, str2);
strcat(dest, str3);
如果在另一方面,你使用std::string
然后+
可以链接string1 + string2 + string3
。
看起来他的问题是关于多重连接的表现 - 它是否为链中的每个步骤创建了一个新的中间字符串,而不是一次将它们全部组合起来? – Barmar
当心[Schlemiel the Painter](https://en.wikichip.org/wiki/schlemiel_the_painter%27s_algorithm)。 –
你是正确的,每个连接可能需要分配。考虑这样一个表达式,其中每个变量是一个字符串:
a = b + c + d + e;
这需要三个级联的操作和三个临时对象,其每一个都需要一个新的分配。
一个简单的解决方案是使用std::ostringstream
,这不应该要求尽可能多的重新分配:
std::ostringstream ss;
ss << b << c << d << e;
a = ss.str();
然而,如果我们串联只有字符串,我们可以做的更好,并分配正好串的大小合适(C++ 11兼容的实施):
std::size_t total_string_size()
{
return 1;
}
template <typename... T>
std::size_t total_string_size(std::string const &s, T const & ...tail)
{
return s.size() + total_string_size(tail...);
}
void concat_strings_impl(std::string &) { }
template <typename... T>
void concat_strings_impl(std::string &out, std::string const &s, T const & ...tail)
{
out += s;
concat_strings_impl(out, tail...);
}
template <typename... T>
void concat_strings(std::string &out, T const & ...strings)
{
out.clear();
out.reserve(total_string_size(strings...));
concat_strings_impl(out, strings...);
}
现在我们可以调用concat_strings(a, b, c, d, e)
在单个重新分配执行a = b + c + d + e;
等效。 (Demo)
避免多次分配的唯一方法是告诉字符串在连接之前需要变得有多大。
例如,一起加入存储在向量的所有字符串(如列表):
std::string join(std::vector<std::string> const& v)
{
std::string r; // return string
// add up all the string sizes
std::size_t size = 0;
for(auto const& s: v)
size += s.size();
// reserve that much space all at once (one allocation)
r.reserve(size);
// now do the concatenations
for(auto const& s: v)
r += s;
return r;
}
除非你有导致不(你异型,发现性能不合格),只要用'运营商+'像:'auto foo = string1 + string2 +“一些文本”+ string3;' – NathanOliver
你只是想协调一堆随机字符串吗?如果是这样,那么只需使用“+”运算符。 –