自定义迭代器运算符重载

时间:2016-10-13 16:25:47

标签: c++ stl iterator std stdmap

我正在尝试实现自定义迭代器的->运算符。但是我没有准确地定义它们。

我的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-&gt;,但问题是我并没有完全得到如何返回迭代器当前指向的键和值对的指针:

我目前的实施是:

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

3 个答案:

答案 0 :(得分: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));
}

演员阵容有点难看,但这就是为什么你把它封装在你很少需要看的代码中。

答案 1 :(得分:0)

如果您真正担心的是泄漏记忆的可能性,您可以将unique_ptr返回pair。这将确保只要不再引用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,如果pairKey_T的类型也可以复制,则可以按值返回Mapped_T

根据Key_TMapped_T的可能类型,在模板代码中使用对时,需要注意那些被引用的类型。可能会引起头痛。

请参阅: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; }
};

但你最终可能会后悔。

答案 2 :(得分:0)

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

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