从std :: unordered_set <char>有效构造std :: string

sal*_*eph 6 c++ string unordered-set c++11

我有一个无序的字符集

std::unordered_set<char> u_setAlphabet;
Run Code Online (Sandbox Code Playgroud)

然后我想从集合中获取std :: string的内容.我的实现现在看起来像这样:

std::string getAlphabet() {
    std::string strAlphabet;
    for (const char& character : u_setAlphabet)
        strAlphabet += character;
    return strAlphabet;
}
Run Code Online (Sandbox Code Playgroud)

这是解决此任务的好方法吗?对于大型u_setAlphabet(多个reallocs?),对字符串添加signle chars似乎不是最佳选择.还有其他方法吗?

xto*_*ofl 12

std::string一个构造函数:

auto s = std::string(begin(u_setAlphabet), end(u_setAlphabet));
Run Code Online (Sandbox Code Playgroud)


Ker*_* SB 12

最简单,最易读和最有效的答案是:

return std:string(s.begin(), s.end());
Run Code Online (Sandbox Code Playgroud)

实现可以选择预先检测范围的长度并且仅分配一次; 当给定前向迭代器范围时,libc ++和libstdc ++都会这样做.

string班还为您提供reserve,就像vector,管理能力:

std::string result
result.reserve(s.size());
for (unsigned char c : s) result.push_back(c);   // or std::copy
return result;
Run Code Online (Sandbox Code Playgroud)

它还提供了assign,appendinsert成员函数,而是因为那些提供强大的异常保证,他们可能有破坏旧人之前分配一个新的缓冲区(感谢@TC指出这个关键的细节!).如果现有容量足够,则libc ++实现不会重新分配,而GCC5的libstdc ++实现无条件地重新分配.

  • @saleph不,因为`std :: set <T> :: iterator`只满足BidirectionalIterator`std :: distance`因此是O(N)操作.但是,`std :: set <T> :: size`是一个恒定时间操作. (3认同)
  • 只有当你知道自己真的处于性能关键代码并且通过测量它找到了差异时,我才会推荐`reserve()`代码.它会破坏你的代码,但如果增益合理,那就没关系.即使构造函数采用迭代器,一个好的标准库实现也只会保留一次内存.你得到的唯一开销就是遍历前面找到大小的遍历. (2认同)

Vla*_*cow 10

最好使用acepts迭代器的构造函数.例如

std::string getAlphabet() {
    return { u_setAlphabet.begin(), u_setAlphabet.end() };
}
Run Code Online (Sandbox Code Playgroud)