【问题标题】:Custom iterator operator overloading自定义迭代器运算符重载
【发布时间】:2017-02-22 21:22:28
【问题描述】:

我正在尝试实现自定义迭代器的-> 运算符。但是我不知道如何精确定义它们。

我的 Iterator 类和 MapNode 定义如下:

template <typename Key_T,typename Mapped_T>
class Map<Key_T,Mapped_T>::Iterator
{
    MapNode<Key_T,Mapped_T>* curr;
}

template <typename Key_T,typename Mapped_T>
class MapNode
{
    Key_T key;
    Mapped_T value;
    MapNode *up,*down,*prev,*next;
    friend class Map<Key_T,Mapped_T>;
};

现在我想重载 operator->,但问题是我没有完全了解如何返回迭代器当前指向的键和值对的指针:

我目前的实现是:

template <typename Key_T,typename Mapped_T>
std::pair<const Key_T, Mapped_T>*
Map<Key_T,Mapped_T>::Iterator::operator->() const
{
    const Key_T currKey = (this->curr)->key;
    const Mapped_T currVal = (this->curr)->value;

    ValueType* vt = new ValueType(std::make_pair(currKey,currVal));

    return vt;
}

但我担心这会导致内存泄漏,因为 ValueType 指针内存永远不会被释放。

有人可以指导我如何正确完成这项工作吗?

请帮忙。

[ValueType is defined as std::pair<const Key_T, Mapped_T>]

【问题讨论】:

    标签: c++ stl iterator std stdmap


    【解决方案1】:

    我首先将 MapNode 中的值存储在 std::pair 中:

    template <typename Key_T,typename Mapped_T>
    class MapNode
    {
        std::pair<Key_T, Mapped_T> value;
        MapNode *up,*down,*prev,*next;
        friend class Map<Key_T,Mapped_T>;
    };
    

    然后迭代器可以只返回该对的地址。

    template <typename Key_T,typename Mapped_T>
    std::pair<const Key_T, Mapped_T> *
    Map<Key_T,Mapped_T>::Iterator::operator->() const
    {
        using ptr = std::pair<const Key_T, Mapped_T> *;
        return (ptr)(&(curr->value));
    }
    

    演员表有点难看,但这就是为什么你将它封装在一段你很少看的代码中。

    【讨论】:

      【解决方案2】:

      如果您真正担心的是内存泄漏的可能性,您可以将unique_ptr 返回到pair。这将确保 new'd 对在不再被引用时将被删除。

      语法是:

      template <typename Key_T,typename Mapped_T>
      std::unique_ptr<std::pair<const Key_T, Mapped_T>>
      Map<Key_T,Mapped_T>::Iterator::operator->() const
      {
          const Key_T currKey = (this->curr)->key;
          const Mapped_T currVal = (this->curr)->value;
      
          return std::make_unique<ValueType>(std::make_pair(currKey,currVal));
      }
      

      另外,由于 std::pair 可以被复制,如果 Key_TMapped_T 的类型也可能是可复制的,您可以按值返回 pair。..

      根据Key_TMapped_T 的可能类型,在这样的模板代码中使用pair 时,您需要小心这些类型是引用。会引起头痛。

      见:std::pair of references

      如果你真的真的很想返回一个指向某个东西的指针,你可以做这样的事情:

      template <typename T> class myIterator {
        T m_current;
      public:
        bool next() { move_to_next(m_current); } // Or however you increment.
        T& read() { m_current; }
      };
      

      但你最终可能会后悔。

      【讨论】:

        【解决方案3】:

        你必须写一个包装器,比如

        template <typename Key, typename Value>
        struct Wrapper
        {
            std::pair<const Key&, Value>* operator -> () { return &p; }
        
            std::pair<const Key&, Value> p;   
        };
        

        你的迭代器变成:

        template <typename Key_T,typename Mapped_T>
        class Map<Key_T,Mapped_T>::Iterator
        {
        public:
            // ...
        
            Wrapper<Key_T, Mapped_T> operator->() const { return {{curr->key, curr->value}}; }
        private:
            MapNode<Key_T,Mapped_T>* curr;
        };
        

        Demo

        【讨论】:

          猜你喜欢
          • 2013-12-17
          • 2011-10-18
          • 2020-06-14
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-12-07
          • 2013-09-07
          相关资源
          最近更新 更多