我听到有一些人对std :: string中的“+”运算符表示担忧,并提出各种加速字符串连接的解决方案。这些方法是否真的必要?如果是,什么是在C ++ 中拼接字符串的最佳方式?
我听到有一些人对std :: string中的“+”运算符表示担忧,并提出各种加速字符串连接的解决方案。这些方法是否真的必要?如果是,什么是在C ++ 中拼接字符串的最佳方式?
如果你预先分配(保留)结果字符串中的空间,那么性能最佳。
Original Answer翻译成"最初的回答"
template<typename... Args>
std::string concat(Args const&... args)
{
size_t len = 0;
for (auto s : {args...}) len += strlen(s);
std::string result;
result.reserve(len); // <--- preallocate result
for (auto s : {args...}) result += s;
return result;
}
使用方法:
std::string merged = concat("This ", "is ", "a ", "test!");
https://github.com/pedro-vicente/table-string
对于Visual Studio 2015,x86调试构建,相对于C++ std::string有显著的改进。
| API | Seconds
| ----------------------|----|
| SDS | 19 |
| std::string | 11 |
| std::string (reserve) | 9 |
| table_str_t | 1 |
std::string
感兴趣。他们并不要求使用其他字符串类。 - underscore_d您可以尝试为每个项目设置内存预留来解决此问题:
namespace {
template<class C>
constexpr auto size(const C& c) -> decltype(c.size()) {
return static_cast<std::size_t>(c.size());
}
constexpr std::size_t size(const char* string) {
std::size_t size = 0;
while (*(string + size) != '\0') {
++size;
}
return size;
}
template<class T, std::size_t N>
constexpr std::size_t size(const T (&)[N]) noexcept {
return N;
}
}
template<typename... Args>
std::string concatStrings(Args&&... args) {
auto s = (size(args) + ...);
std::string result;
result.reserve(s);
return (result.append(std::forward<Args>(args)), ...);
}
基准测试使用Visual Studio C/C++ 17.2.5和Boost 1.79.0在Ryzen 5600x上进行:
n iter = 10
n parts = 10000000
total string result length = 70000000
Boost join: 00:00:02.105006
std::string append (Reserve): 00:00:00.485498
std::string append (simple): 00:00:00.679999
Note: times are cumulative sums over all iterations.
n iter = 100
n parts = 1000000
total string result length = 6000000
Boost join: 00:00:01.953999
std::string append (Reserve): 00:00:00.535502
std::string append (simple): 00:00:00.679002
Note: times are cumulative sums over all iterations.
libstdc++
中的实现方式。因此,当使用临时对象调用 operator+ 时,它几乎可以达到与其他方式相同的性能 - 这可能是默认情况下选择它的论点,出于可读性的考虑,除非有基准测试表明它是瓶颈。但是,一个标准化的可变参数append()
不仅最优,而且更加易读... - underscore_d