我有一个非常高性能的应用程序,我真的想避免复制一个保存在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;
}
这是可能的,还是我必须在使用之前复制该元素?
答案 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)允许您使用数组,并且数组索引非常快。