实现一个保证不移动的"字符串池"

Cha*_*hap 9 c++ string c++-standard-library string-pool

我需要一个"字符串池"对象,我可以在其中重复插入"字符序列"(我使用这个短语来表示"字符串"而不会将其与std :: string或C字符串混淆),获取指向序列的指针,如果/当池需要增长时,保证指针不会失效.使用简单std::string的池作为池将无法工作,因为当字符串超出其初始容量时可能会重新分配字符串,从而使所有先前指针无效.

游泳池不会无限制地增长 - 我会在其上调用一个clear()方法明确定义点- 但我也不想保留任何最大容量.它应该能够在不移动的情况下成长.

我正在考虑的一种可能性是将每个新的字符序列插入到a中forward_list<string>并获得begin()->c_str().另一个是插入unordered_set<string>,但我很难找到当unordered_set必须增长时会发生什么.我正在考虑的第三种可能性(不太热情)是滚动我自己的1K缓冲区链,我将其连接到字符序列中.这具有(我猜)具有最高性能的优势,这是该项目的要求.

我有兴趣听听其他人如何建议接近这个.

更新1:编辑以澄清我对短语"chars序列"的使用等同于"字符串"的一般概念,而不暗示std :: string或以null结尾的char数组.

seh*_*ehe 8

我过去曾使用过这种方法:

using Atom = const char*;

Atom make_atom(string const& value)
{
    static set<string> interned;
    return interned.insert(value).first->c_str();
}
Run Code Online (Sandbox Code Playgroud)

显然,如果您想/需要清除该组,您可以在更广泛的范围内使用它.

为了更高效率,将琴弦移动/放入集合中.

更新我已添加此方法以实现完整性.在科利鲁看到它

#include <string>
#include <set>
using namespace std;

using Atom = const char*;

template <typename... Args>
typename enable_if<
    is_constructible<string, Args...>::value, Atom
>::type emplace_atom(Args&&... args)
{
    static set<string> interned;
    return interned.emplace(forward<Args>(args)...).first->c_str();
}

#include <iostream>

int main() {
    cout << emplace_atom("Hello World\n");
    cout << emplace_atom(80, '=');
}
Run Code Online (Sandbox Code Playgroud)

  • @Chap:关联容器具有以下属性:"insert和emplace成员不应影响迭代器的有效性和对容器的引用,并且擦除成员应仅使迭代器和对已擦除元素的引用无效"(来自C++ 11)标准).`unordered_set`是一个关联容器. (2认同)