簡體   English   中英

在 unordered_map 中查找的性能

[英]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[]很可能在內部使用findinsert 例如,IIRC 就是 Miscrosoft 的std::map實現的情況。

編輯:我想說的是operator[]並不神奇,它仍然需要先進行查找。 從我在 Boost 1.46.0 中看到的內容來看, find和 said 操作符都在內部使用find_iterator

通常最好使用find進行查找,因為您的代碼將更具可重用性和健壯性(例如,您永遠不會意外插入某些內容),尤其是在某種通用代碼中。

無序容器上的findoperator[]平均為 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM