如何从 std::vector<string> 构造 std::string?
我想从 std::vector
构建一个 std::string
.
I'd like to build a std::string
from a std::vector<std::string>
.
我可以使用 std::stringsteam
,但想象有一种更短的方法:
I could use std::stringsteam
, but imagine there is a shorter way:
std::string string_from_vector(const std::vector<std::string> &pieces) {
std::stringstream ss;
for(std::vector<std::string>::const_iterator itr = pieces.begin();
itr != pieces.end();
++itr) {
ss << *itr;
}
return ss.str();
}
我还能怎么做?
推荐答案
C++03
std::string s;
for (std::vector<std::string>::const_iterator i = v.begin(); i != v.end(); ++i)
s += *i;
return s;
C++11 (MSVC 2010 子集)
std::string s;
std::for_each(v.begin(), v.end(), [&](const std::string &piece){ s += piece; });
return s;
C++11
std::string s;
for (const auto &piece : v) s += piece;
return s;
不要使用std::accumulate
进行字符串连接,这是一个经典的Schlemiel 画家的算法,甚至比在 C 中使用 strcat
的通常示例还要糟糕.如果没有 C++11 移动语义,它会导致两个不必要的副本向量的每个元素的累加器.即使使用移动语义,它仍然会为每个元素产生一个不必要的累加器副本.
Don't use std::accumulate
for string concatenation, it is a classic Schlemiel the Painter's algorithm, even worse than the usual example using strcat
in C. Without C++11 move semantics, it incurs two unnecessary copies of the accumulator for each element of the vector. Even with move semantics, it still incurs one unnecessary copy of the accumulator for each element.
上面的三个例子是O(n).
std::accumulate
对于字符串是 O(n2).
您可以通过提供一个字符串来使 std::accumulate
O(n)自定义函子:
You could make
std::accumulate
O(n) for strings by supplying a custom functor:
std::string s = std::accumulate(v.begin(), v.end(), std::string{},
[](std::string &s, const std::string &piece) -> decltype(auto) { return s += piece; });
注意 s
必须是对非常量的引用,即 lambda 返回类型必须是引用(因此 decltype(auto)
),并且主体必须使用+=
不是 +
.
Note that s
must be a reference to non-const, the lambda return type
must be a reference (hence decltype(auto)
), and the body must use
+=
not +
.
C++20
在预期成为 C++20 的当前草案中,std::accumulate
的定义是 改变在附加到累加器时使用 std::move
,所以从 C++20 开始,accumulate
将是 O(n) 用于字符串,并且可以用作单行:
C++20
In the current draft of what is expected to become C++20, the definition of std::accumulate
has been altered to use std::move
when appending to the accumulator, so from C++20 onwards, accumulate
will be O(n) for strings, and can be used as a one-liner:
std::string s = std::accumulate(v.begin(), v.end(), std::string{});
相关文章