我必须通过几个不同的标识符访问我的对象(来自一个类的多个实例),并且不知道哪个是存储从标识符到对象的映射的最佳方式。 我充当两个世界之间的“连接器”,每个世界都有自己的标识符,我必须使用/支持。 如果可能的话,我想阻止使用指针。
第一个想法是将对象放在List / Vector中,然后为每种类型的标识符创建一个映射。不久,我不得不意识到std-container不支持存储引用。
接下来的想法是将对象保留在向量中,然后将索引放在地图中。这里的问题是我没有找到vector的index_of,并且只要没有人使用insert或erase就可以将对象存储在对象中。
创建对象时唯一的标识是字符串,为了提高性能,我不想将此字符串用作地图的标识符。
这是一个问题解决最好的指针还是有人知道如何处理它?</ p>
由于
答案 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*
以避免争用;如果您的用例涉及更多阅读而非写作,这将特别有用。