哪些容器可以存储通过不同标识符访问的对象?

时间:2014-03-11 08:19:29

标签: c++ c++-standard-library

我必须通过几个不同的标识符访问我的对象(来自一个类的多个实例),并且不知道哪个是存储从标识符到对象的映射的最佳方式。 我充当两个世界之间的“连接器”,每个世界都有自己的标识符,我必须使用/支持。 如果可能的话,我想阻止使用指针。

第一个想法是将对象放在List / Vector中,然后为每种类型的标识符创建一个映射。不久,我不得不意识到std-container不支持存储引用。

接下来的想法是将对象保留在向量中,然后将索引放在地图中。这里的问题是我没有找到vector的index_of,并且只要没有人使用insert或erase就可以将对象存储在对象中。

创建对象时唯一的标识是字符串,为了提高性能,我不想将此字符串用作地图的标识符。

这是一个问题解决最好的指针还是有人知道如何处理它?<​​/ p>

由于

2 个答案:

答案 0 :(得分:0)

您是否考虑过in-memory SQLite数据库? SQL为您提供了许多访问相同数据的方法。例如,您的架构可能如下所示:

CREATE TABLE Widgets {
  -- Different ways of referring to the same thing.
  name STRING,
  id INTEGER,

  -- Non-identifying characteristics.
  mass_kg FLOAT,
  length_m FLOAT,
  cost_cents INTEGER,
  hue INTEGER;
}

然后您可以使用不同的标识符进行查询:

SELECT mass_kg from Widgets where name = $name

SELECT mass_kg from Widgets where id = $id

当然,SQL允许你做更多的事情。这将使您可以在将来轻松扩展库的功能。

另一个优点是SQL是声明性的,这通常使它更简洁和可读。

在最新版本中,SQLite支持对同一数据库的并发访问。随着时间的推移,并发模型变得越来越强大,因此您必须确保理解您正在使用的版本所提供的模型。可以在sqlite的网站上找到latest version文档。

答案 1 :(得分:0)

使用指针似乎很合理。以下是您可以实施的建议API:

class WidgetDatabase {
 public:
  // Returns true if widget was inserted.
  // If there is a Widget in *this with the same name and/or id,
  // widget is not inserted.
  bool Insert(const std::string& name, int id, const Widget& widget);

  // Caller does NOT own returned pointer (do not delete it!).
  // null is returned if there is no such Widget.
  const Widget* GetByName(const string& name) const;
  const Widget* GetById(int id) const;

 private:
  std::set<Widget> widgets_;
  std::map<std::string, Widget*> widgets_by_name_;
  std::map<int, Widget*> widgets_by_id_;
};

我认为这应该非常简单。您只需要确保保持以下不变量:

  

w在widgets_中iff指向它的指针位于widgets_by _ *

我认为您遇到的主要缺陷是确保在调用Insert时,名称和ID不在widgets_by_ *中。

这个线程应该很容易安全;只需输入mutex成员变量和一些本地lock_guards。 (可选)在shared_lock_guard方法中使用Get*以避免争用;如果您的用例涉及更多阅读而非写作,这将特别有用。