[英]performance of find in an unordered_map
我知道這可能是一個愚蠢的問題,但我想確定一下,但我無法輕易找到這些信息。
find() 在無序 map 中的性能特征是什么? 它是否與正常查找一樣快/幾乎一樣快?
IE
std::string defaultrow = sprite.attribute("defaultrow").value();
auto rclassIt = Rows::NameRowMap.find(defaultrow);
if (rclassIt != Rows::NameRowMap.end())
defRow = rclassIt->second;
對比
std::string defaultrow = sprite.attribute("defaultrow").value();
defRow = Rows::NameRowMap[defaultrow];
其中Rows::NameRowMap
是將字符串索引映射到 int 的無序 map。
就我而言,我不確定密鑰是否會事先存在,所以第一個解決方案對我來說似乎更安全,但如果我能保證存在,第二種情況會更快(忽略我正在做的額外檢查) ? 如果是這樣,為什么? 如果重要的話,我正在使用 1.46 boost 實現
operator[]
很可能在內部使用find
和insert
。 例如,IIRC 就是 Miscrosoft 的std::map
實現的情況。
編輯:我想說的是operator[]
並不神奇,它仍然需要先進行查找。 從我在 Boost 1.46.0 中看到的內容來看, find
和 said 操作符都在內部使用find_iterator
。
通常最好使用find
進行查找,因為您的代碼將更具可重用性和健壯性(例如,您永遠不會意外插入某些內容),尤其是在某種通用代碼中。
無序容器上的find
和operator[]
平均為 O(1),最壞情況為 O(n) - 這取決於您的 hash function 的質量。
它們具有相同的 O(1) 的攤銷復雜度,但是當找不到值時,運算符也會創建一個新元素。 如果找到該值,則性能差異應該很小。 我的提升有點舊 - 版本 1.41,但希望沒關系。 這是代碼:
// find
//
// strong exception safety, no side effects
template <class H, class P, class A, class G, class K>
BOOST_DEDUCED_TYPENAME hash_table<H, P, A, G, K>::iterator_base
hash_table<H, P, A, G, K>::find(key_type const& k) const
{
if(!this->size_) return this->end();
bucket_ptr bucket = this->get_bucket(this->bucket_index(k));
node_ptr it = find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(it))
return iterator_base(bucket, it);
else
return this->end();
}
// if hash function throws, basic exception safety
// strong otherwise
template <class H, class P, class A, class K>
BOOST_DEDUCED_TYPENAME hash_unique_table<H, P, A, K>::value_type&
hash_unique_table<H, P, A, K>::operator[](key_type const& k)
{
typedef BOOST_DEDUCED_TYPENAME value_type::second_type mapped_type;
std::size_t hash_value = this->hash_function()(k);
bucket_ptr bucket = this->bucket_ptr_from_hash(hash_value);
if(!this->buckets_) {
node_constructor a(*this);
a.construct_pair(k, (mapped_type*) 0);
return *this->emplace_empty_impl_with_node(a, 1);
}
node_ptr pos = this->find_iterator(bucket, k);
if (BOOST_UNORDERED_BORLAND_BOOL(pos)) {
return node::get_value(pos);
}
else {
// Side effects only in this block.
// Create the node before rehashing in case it throws an
// exception (need strong safety in such a case).
node_constructor a(*this);
a.construct_pair(k, (mapped_type*) 0);
// reserve has basic exception safety if the hash function
// throws, strong otherwise.
if(this->reserve_for_insert(this->size_ + 1))
bucket = this->bucket_ptr_from_hash(hash_value);
// Nothing after this point can throw.
return node::get_value(add_node(a, bucket));
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.