少なくとも可能性をSTLに制限した場合、両側での高速挿入と同じコンテナーでの高速検索の両方を行うことはできません。よりエキゾチックな非標準のコンテナが役立つ場合があります。
しかし、これらの場合に私が一般的に選択するアプローチは、2つのコンテナーを使用することです。要素を格納するための明白なオプションはstd::dequeです。検索の場合は、std::map<K,V>
ここで、Vは両端キューのイテレータです。dequesでの挿入/削除は、関係のないイテレータを無効にしないため、マップとdequeを常に同期することを忘れないでください(つまり、dequeで挿入または削除を行う場合は、マップでも同期してください)。 。イテレータを使用する代わりに、別のより簡単で安全なオプション(マップで検索した後、見つかった要素だけが必要な場合(近くの要素にアクセスする必要がない場合など))は、両端キューとマップの両方をスマートにすることです。実際のオブジェクト(より具体的には、shared_ptr)へのポインター。繰り返しますが、両方の同期を保つように注意する必要があります。同期が緩んでも壊滅的ではありませんが、もちろん、プログラムの一貫性が損なわれる可能性があります。
struct MyItem
{
std::string name;
int something;
int another;
MyItem(const std::string &name_, int something_, int another_)
:name(name_), something(something_), another(another_) {}
};
class MyContainer
{
public:
typedef std::shared_ptr<MyItem> MyItemPtr;
void push_front(MyItemPtr item)
{
deque.push_front(item);
assert(map.find(item->name) == map.end());
map[item->name] = item;
}
void push_back(MyItemPtr item)
{
deque.push_back(item);
assert(map.find(item->name) == map.end());
map[item->name] = item;
}
MyItemPtr pop_front()
{
item = deque.front();
deque.pop_front();
map.erase(item->name);
return item;
}
MyItemPtr pop_back()
{
item = deque.back();
deque.pop_back();
map.erase(item->name);
return item;
}
MyItemPtr find(const std::string &name)
{
std::map<std::string, MyItemPtr>::iterator iter = map.find(name);
if (iter == map.end())
return MyItemPtr();
else
return iter->second;
}
private:
std::deque<MyItemPtr> deque;
std::map<std::string, MyItemPtr> map;
};
それを使用するには:
MyContainer container;
MyContainer::MyItemPtr a(new MyItem("blah", 1, 2));
container.push_back(a);
MyContainer::MyItemPtr b(new MyItem("foo", 5, 6));
container.push_front(b);
MyContainer::MyItemPtr f = container.find("blah");
if (f)
cout << f->name << ", " << f->something << ", " << f->another;