是否可以访问unordered_map中的元素而无需复制它?

时间:2017-08-29 16:13:37

标签: c++

我有一个非常高性能的应用程序,我真的想避免复制一个保存在unordered_map中的字符串。我希望能够做的一个例子是将此字符串与本地字符串变量进行比较。

如,

unordered_map<string,string> X;
string test = "def";
X["abc"] = test;

//other operations here...

string* map_entry = X.???; //some operation that doesn't make a copy of the string

size_t map_entry_size = (*map_entry).size();

for (size_t i = 0; i < map_entry_size; ++i)
{
if ((*map_entry)[i] != test[i])
  throw 1;
}

这是可能的,还是我必须在使用之前复制该元素?

1 个答案:

答案 0 :(得分:3)

[]运算符将返回引用或const引用,因此不存在副本。迭代器会给你一个std::pair<std::string, std::string>的引用,所以那里再没有副本。

std::string &map_entry = X["abc"]; // Reference to value, no copy
std::string *map_entry = &X["abc"]; // If you need a pointer

如果您确实需要指针,则&map["key"]&iterator->second有效。

如果您正在寻找性能,避免或至少小心std::string作为键是一个更重要的收益,特别是如果键不是很短。

当然不要仅仅因为无序地图是O(1)std::unordered_map<std::string, T>几乎与使用整数键一样快,并且它甚至远离可能只是普通数组的密集整数键(即使两者都是O(1))。

  • 您需要临时std::string。最坏的情况是动态内存分配。对于小字符串,您使用的标准库实现可能具有“小字符串优化”,但这仍然是副本。

    如果可能,您想使用已经从某个地方制作的现有std::string

  • 您需要计算哈希值(默认值使用std::hash),以及字符串长度为O(n)的字符串。

    std::string没有办法缓存它的哈希,所以重用(例如一个常量/静态)std::string并不能避免这种情况,尽管你可以创建自己的字符串包装器。

  • 因为哈希可能会发生冲突,如果unordered_map确实找到了一个条目,那么无论如何它都需要进行完整的字符串比较,以防万一,这又是O(n)的字符串长度(所以实际上根本找不到任何东西比找到正确的东西更快。

使用一个整数或其他小的固定大小的键(也可以考虑如果你知道你的字符串总是小于4或8个字节,你可以使用“null padding”这个整数)使哈希变得简单一段数学,比较单一操作。

使用密集整数(比如枚举形式0到16)允许您使用数组,并且数组索引非常快。