自定义迭代器运算符重载

Custom iterator operator overloading

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

我的迭代器 class 和 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->,但问题是我不知道如何 return 迭代器当前指向的键和值对的指针:

我当前的实现是:

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>]

如果您真正担心的是内存泄漏的可能性,您可以 return 一个 unique_ptrpair。这将确保 new 对不再被引用时将被删除。

语法为:

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 的类型可能是也可复制..

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

参见:std::pair of references

如果你真的真的很想 return 一个指向某物的指针,你可以做这样的事情,这真的很骇人听闻:

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

但你最终可能会后悔。

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

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

我首先将 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>;
};

然后迭代器可以 return 那对地址。

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));
}

转换有点难看,但这就是为什么您将它封装在一段您很少需要查看的代码中。