【问题标题】:Should I manipulate a C++ map's value via a pointer or by updating the record?我应该通过指针还是通过更新记录来操作 C++ 映射的值?
【发布时间】:2011-04-20 21:12:20
【问题描述】:

我正在使用 C++ std::map 来保存大量实体:

using std::map;  
map {structureEntityID, classEntityRecord} tableEntityRecords; //(replace {}s with arrows)

我会经常修改表中的实体(每秒多次)。是通过指针修改这些记录更好,还是制作本地副本,修改它,然后更新表更好?

例如...

通过指针:

classEntityRecord* getEntityRecord(structureEntityID entityID)  
{  
    map {structureEntityID, classEntityRecord}::iterator iteratorEntityRecord;  
    iteratorEntityRecord = tableEntityRecords.find(entityID);  
    return &iteratorEntityRecord->second;  
}  

classEntityRecord *entityRecord;  
entityRecord = getEntityRecord(entityID);  
entityRecord->x = 15;  

通过复制/修改/更新:

classEntityRecord getEntityRecord(structureEntityID entityID)  
{  
    map {structureEntityID, classEntityRecord}::iterator iteratorEntityRecord;  
    iteratorEntityRecord = tableEntityRecords.find(entityID);  
    return iteratorEntityRecord->second;  
}

classEntityRecord entityRecord;  
entityRecord = getEntityRecord(entityID);  
entityRecord.x = 15;  
tableEntityRecords[entityID] = entityRecord; 

我认为使用指针会更好,但这是我第一次使用 C++ 映射,所以我不完全了解它们是如何工作的。

我最担心的是,如果我将指针指向表中的某个值,C++ 映射是否可能被重新排序并且该指针不再有效?该程序是多线程的,因此可以在修改其他实体的同时将实体添加到表中。

感谢您的帮助!

【问题讨论】:

  • 当查询到的实体没有找到时,find()返回map<..,..>::endl()。你也应该处理这种情况。
  • 同意,我有一个附加功能,可以在检索记录之前检查记录是否存在(未显示)。

标签: c++ pointers stl map


【解决方案1】:

您应该考虑引用 (&) 而不是指针 (*)。就目前而言,您的 getEntityRecord 返回地图元素值的副本,因此不会通过地图看到对返回值的更改。如果你改变这个函数来返回一个引用,它会做你想做的。

classEntityRecord& getEntityRecord(structureEntityID entityID)

map::find 返回一个iterator,其中的second 字段包含对map 成员值的引用。您可以使用此引用安全地修改 map 成员值,而不必担心 map 被修改,只要没有其他人删除该条目

来自map documentation for SGI STL

地图有一个重要的属性: 将新元素插入地图 不会使迭代器无效 指向现有元素。擦除一个 地图中的元素也没有 使任何迭代器无效,除了 当然,对于实际上 指向正在执行的元素 删除。

【讨论】:

  • 太好了,感谢您的帮助。对于您的建议,我的代码很容易交换。 :-)
  • @Clint - 一般来说,尽可能避免使用原始指针。引用不能使您的代码崩溃,因为它是 NULL。
【解决方案2】:

至于您担心“如果我将指针指向表中的某个值,C++ 映射是否可能被重新排序并且该指针不再有效?”,答案是您可能不需要太担心 - 但确实需要小心(假设您使用迭代器而不是指针,这应该很容易,因为迭代器在设计上就像指针一样)。

以下是标准对迭代器的有效性以及对关联容器(如 std::map(23.1.2/8 “关联容器”)中的对象的引用)的说明:

插入成员不会影响迭代器和对容器的引用的有效性,而擦除成员只会使迭代器和对被擦除元素的引用无效。

【讨论】:

  • 感谢您的帮助!特别指出引用不会失效。
猜你喜欢
  • 2022-12-21
  • 2012-04-28
  • 1970-01-01
  • 1970-01-01
  • 2014-07-26
  • 2011-04-30
  • 1970-01-01
  • 1970-01-01
  • 2015-02-02
相关资源
最近更新 更多