通过引用 std::list 中的元素从 std::unordered_map 中删除元素

发布于 2025-01-13 18:14:15 字数 2195 浏览 6 评论 0原文

我正在实现 LRUCache,但在理解从 std::unordered_map 中删除方面遇到了问题。互联网上的所有示例都表明,可以使用 std::list 中的元素引用从 std::unordered_map 中删除元素(通过使用 std: :list::back())。为什么会这样呢?我查看了 std::unordered_map::erase() 的文档,它接受映射迭代器或键作为参数,但肯定不是对另一个数据结构中元素的引用?是否有一些我不明白的关于迭代器的特定转换或某些东西?先感谢您!

PS 我会感谢对我的代码结构和实现的任何评论。

这是我的缓存代码:

#ifndef LRUCACHE_H
#define LURCACHE_H

#include <list>
#include <unordered_map>
#include <assert.h>
#include <iostream>

template<typename T, typename KeyT = T>
class LRUCache
{

using ListItr = typename std::list<T>::iterator;

public:
    LRUCache(int size) : m_size(size)
    {

    }

    int size() const
    {
        return m_size;
    }

    bool isFull() const
    {
        return m_size == m_cache.size();
    }

    bool contains(const KeyT& key)
    {
        m_lookup_table.find(key) != m_lookup_table.end();
    }

    T get(const KeyT& key)
    {
        auto hit = m_lookup_table.find(key);
        assert("No such element present" && hit != m_lookup_table.end());
        if (hit != m_lookup_table.begin()) {
            m_cache.splice(m_cache.begin(), m_cache, hit->second);
        }
        return *(hit->second);
    }

    void set(const KeyT& key, const T& value)
    {
        auto hit = m_lookup_table.find(key);
        if (hit == m_lookup_table.end()) {
            if (isFull()) {
                m_lookup_table.erase(m_cache.back()); // <-- I don't understand this
                m_cache.pop_back();
            }
            m_cache.push_front(value);
            m_lookup_table[key] = m_cache.begin();
            return;
        }

        if (hit->second != m_cache.begin()) {
            m_cache.splice(m_cache.begin(), m_cache, hit->second);
        }
    }

    void display() const
    {
        for (const auto& e : m_cache) {
            std::cout << e << " ";
        }
        std::cout << std::endl;
    }

private:
    int m_size;
    std::list<T> m_cache;
    std::unordered_map<KeyT, ListItr> m_lookup_table;
};

#endif

I'm implementing my LRUCache and I have an issue with understanding the removal from std::unordered_map. All the examples in The Internet show that it's possible to remove an element from std::unordered_map using reference to element from std::list (by using std::list::back()). Why is that so? I checked out the documentation for std::unordered_map::erase() and it accepts map iterator or key as an argument, but defenitely not a reference to an element in another data structure? Is there some specific converstion or somethign about iterators I don't understand? Thank you in advance!

P.S. I would appriciate any comments on my code structure and implementation.

Here's my code for cache:

#ifndef LRUCACHE_H
#define LURCACHE_H

#include <list>
#include <unordered_map>
#include <assert.h>
#include <iostream>

template<typename T, typename KeyT = T>
class LRUCache
{

using ListItr = typename std::list<T>::iterator;

public:
    LRUCache(int size) : m_size(size)
    {

    }

    int size() const
    {
        return m_size;
    }

    bool isFull() const
    {
        return m_size == m_cache.size();
    }

    bool contains(const KeyT& key)
    {
        m_lookup_table.find(key) != m_lookup_table.end();
    }

    T get(const KeyT& key)
    {
        auto hit = m_lookup_table.find(key);
        assert("No such element present" && hit != m_lookup_table.end());
        if (hit != m_lookup_table.begin()) {
            m_cache.splice(m_cache.begin(), m_cache, hit->second);
        }
        return *(hit->second);
    }

    void set(const KeyT& key, const T& value)
    {
        auto hit = m_lookup_table.find(key);
        if (hit == m_lookup_table.end()) {
            if (isFull()) {
                m_lookup_table.erase(m_cache.back()); // <-- I don't understand this
                m_cache.pop_back();
            }
            m_cache.push_front(value);
            m_lookup_table[key] = m_cache.begin();
            return;
        }

        if (hit->second != m_cache.begin()) {
            m_cache.splice(m_cache.begin(), m_cache, hit->second);
        }
    }

    void display() const
    {
        for (const auto& e : m_cache) {
            std::cout << e << " ";
        }
        std::cout << std::endl;
    }

private:
    int m_size;
    std::list<T> m_cache;
    std::unordered_map<KeyT, ListItr> m_lookup_table;
};

#endif

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

枯寂 2025-01-20 18:14:15

erase 有一个重载,它接受 Key (在您的情况下等于 KeyT),而不是迭代器:https://en.cppreference.com/w/cpp/container/unordered_map/erase

请注意,来自 std::listback 不会返回迭代器,而是返回元素(在您的情况下为 T): https://en.cppreference.com/w/cpp/container/list/back

所以我的猜测是代码仅当 KeyT = T 时针对您的默认情况进行编译。

There is an overload of erase that accepts Key (which in your case equals KeyT), not the iterator: https://en.cppreference.com/w/cpp/container/unordered_map/erase.

Note that back from std::list doesn't return an iterator, but the element (in your case T): https://en.cppreference.com/w/cpp/container/list/back

So my guess is that the code only compiles for your default case when KeyT = T.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文