首先,有人可以澄清在C ++中是否使用[]运算符和unordered_map进行查找包装调用find()方法,或者使用[]运算符比find()更快?
其次,在下面的一段代码中,我怀疑在unordered_map中尚未存在键的情况下,我通过行map[key] = value
执行第二次查找以替换在那里创建的默认值当一个键不存在时使用[]运算符。
这是真的,如果是这样的话(可能通过使用指针或其他东西)我可能只会在任何情况下执行一次查找(可能通过存储放置值的位置/读取值的地址)来自)仍然实现相同的功能?显然,如果是这样,这将是一项有用的效率提升。
以下是修改后的代码摘录:
int stored_val = map[key]; // first look up. Does this wrap ->find()??
// return the corresponding value if we find the key in the map - ie != 0
if (stored_val) return stored_val;
// if not in map
map[key] = value;
/* second (unnecessary?) look up here to find position for newly
added key entry */
return value;
答案 0 :(得分:44)
operator[]
将为您输入一个带有默认构造值的条目(如果尚未存在)。它相当于,但可能会比以下更有效地实施:
iterator iter = map.find(key);
if(iter == map.end())
{
iter = map.insert(value_type(key, int())).first;
}
return *iter;
operator[]
可以比使用find()
和insert()
手动完成工作更快,因为它可以节省重新哈希密钥。
在代码中进行多次查找的一种方法是引用值:
int &stored_val = map[key];
// return the corresponding value if we find the key in the map - ie != 0
if (stored_val) return stored_val;
// if not in map
stored_val = value;
return value;
请注意,如果地图中不存在该值,operator[]
将默认构造并插入一个。因此,虽然这样可以避免多次查找,但如果使用default-construct + assign的类型比使用copy-或move-construct慢的类型,它实际上可能会更慢。
虽然使用int
,哪个便宜默认构造为0,但您可以将0视为幻数,意味着为空。这看起来像你的例子中的情况。
如果你没有这样神奇的数字,你有两个选择。你应该使用什么取决于你计算价值的成本。
首先,当散列密钥很便宜但计算价值昂贵时,find()
可能是最佳选择。这将散列两次,但只在需要时计算值:
iterator iter = map.find(key);
// return the corresponding value if we find the key in the map
if(iter != map.end()) return *iter;
// if not in map
map.insert(value_type(key, value));
return value;
但是如果你已经拥有了这个价值,那么你可以非常有效地做到这一点 - 也许比使用上面的参考+幻数更有效:
pair<iterator,bool> iter = map.insert(value_type(key, value));
return *iter.first;
如果map.insert(value_type)
返回的bool为true,则插入该项。否则,它已经存在并且没有进行任何修改。迭代器返回指向映射中的插入值或现有值。对于您的简单示例,这可能是最佳选择。
答案 1 :(得分:10)
你们都可以检查一个元素是否存在,和插入一个新元素(如果它不存在),使用特殊的insert
函数返回一个pair<iterator, bool>
,其中boolean值告诉您该值是否已实际插入。例如,代码here:
unordered_map<char, int> mymap;
pair<unordered_map<char,int>::iterator,bool> ret;
// first insert function version (single parameter):;
mymap.insert ( pair<char,int>('z',200) );
ret=mymap.insert (pair<char,int>('z',500) );
if (ret.second==false)
{
cout << "element 'z' already existed";
cout << " with a value of " << ret.first->second << endl;
}
此处的代码会将对<'z',200>
插入到地图中(如果它不存在)。如果返回的对的第二个元素的值为true,则返回插入它的迭代器,或者,如果该对的第二个元素为false,则返回元素实际所在的迭代器。
答案 2 :(得分:2)
首先,有人可以澄清在C ++中是否使用[]运算符和unordered_map进行查找包装调用Find()方法,或者使用[]运算符比Find()更快?
没有规则。 []
的实现可以使用find()
,它可以自己执行查找,也可以将查找委托给内部find()
也使用的某个私有方法。
也无法保证哪一个更快。 find()
涉及构造和返回迭代器的开销,而[]
如果密钥不存在则可能会更慢,因为在这种情况下它会插入一个新值。
(...)是否有一种方法(可能通过使用指针或其他东西),我可能只会在任何情况下执行一次查找(...)
如果密钥不在地图中,[]
将插入新的默认构造值,并返回引用。因此,您可以存储该引用以保存第二个查找:
int& stored_val = map[key]; // Note the reference
if (stored_val) return stored_val;
// Use the reference to save a second lookup.
stored_val = value;
return value;