2010-10-29 47 views
4

我正在为我的科学软件编写3D网格,我需要遍历网格的节点以获取它们的坐标。我不想将容器中的每个节点对象都放在容器中,而是想在迭代时快速计算坐标。问题是stl :: iterator需要返回对operator*()operator->()的结果的值的引用。STL迭代器:“取消引用”迭代器到临时。可能吗?

下面的一些代码的:


class spGridIterator { 
public: 
    typedef forward_iterator_tag iterator_category; 
    typedef spVector3D value_type; 
    typedef int difference_type; 
    typedef spVector3D* pointer; 
    typedef spVector3D& reference; 

    spGridIterator(spGrid* gr, int index); 

    spGridIterator& operator++(); 
    spGridIterator& operator++(int); 

    reference operator*() const; 
    pointer operator->() const; 

private: 
    spGrid* m_grid; 
    int m_idx; 
}; 

spGridIterator::reference spGridIterator::operator*() const { 
    // return m_grid->GetPoint(m_idx); 
} 

spGridIterator::pointer spGridIterator::operator->() const { 
    // return m_grid->GetPoint(m_idx); 
} 

此方法查询节点坐标由索引提供


spVector3D spGrid::GetPoint(int idx) const { 
    // spVector3D vec = ... calculate the coordinates here ... 
    return vec; 
} 

在此的任何输入?

由于提前, 伊利亚

+0

“问题是stl :: iterator需要返回对运算符*()的结果的引用,或者运算符 - >()的指针”为什么会有这个问题?为了什么? – 2010-10-29 09:07:52

+0

我不确定我真的明白你想要达到什么目的。也许你可以包含一个客户端代码的例子,以了解你如何使用这个集合。 – 2010-10-29 09:13:39

+0

“为什么这是一个问题?为什么?”因为这样我就不得不保留一个实际的变量来指向(或引用)。 – ezpresso 2010-10-29 11:11:51

回答

5

你可以使用一个成员变量来保存它目前指向网格点:

class spGridIterator { 
public: 
    typedef forward_iterator_tag iterator_category; 
    typedef spVector3D value_type; 
    typedef int difference_type; 
    typedef spVector3D* pointer; 
    typedef const spVector3D* const_pointer; 
    typedef const spVector3D& const_reference; 
    typedef spVector3D& reference; 

    spGridIterator(spGrid* gr, int index); 

    spGridIterator& operator++(); 
    spGridIterator& operator++(int); 

    reference operator*(); 
    const_reference operator*() const; 

    pointer operator->(); 
    const_pointer operator->() const; 

private: 
    spGrid* m_grid; 
    int m_idx; 
    mutable spVector3D CurrentPoint; 
}; 

然后引用操作看起来是这样的:

spGridIterator::const_reference spGridIterator::operator*() const { 
    CurrentPoint = m_grid->GetPoint(m_idx); 
    return CurrentPoint; 
} 

感谢@greg指出CurrentPoint需要为mutable才能正常工作。这将是一个懒惰的实现(只有当迭代器被实际解除引用时才获取该点)。渴望的实现会更新迭代器的mutator方法中的CurrentPoint成员(本示例中为operator++变体),使得mutable成为多余。

+0

除非'CurrentPoint'是'mutable','operator *()'不能是'const',对吗? – greg 2013-02-12 18:03:39

+0

这是正确的,这是没有意义的。我确定了答案。 – 2013-02-12 20:09:42

+0

这仍然不完全正确,因为您无法在'const'方法内更改'spGridIterator'对象的状态。除非'CurrentPoint'是'mutable',否则'operator *()'中'CurrentPoint'的赋值不会被编译。 – greg 2013-02-13 13:14:00

1

由于迭代器是一个值对象,为什么不只是将成员设置为想要返回的值,并返回对成员的引用呢?

1

简短的回答是,这将导致未定义的行为,你毕竟返回一个临时的参考!一种选择(如果这个迭代器不需要重新进入,就是让一个类成员(类型为spVector3D)将“返回值”分配给它(当然,您可以通过将参考传递给GetPoint以及索引),然后返回。

+0

感谢您的回应! – ezpresso 2010-10-29 11:33:16

1

我知道这个帖子太旧,但只是因为我有同样的“问题” 和谷歌带我到这里,我会加我的两美分,这里是什么我发现:

至少在C++库有很多的迭代器类型,每一个宣布一些相关的语义的类型是

  • 输入迭代器
  • 前向迭代
  • 双向迭代器
  • 随机访问迭代器
  • 输出迭代

在你的问题情况下,输入迭代器语义契合。特别是在输入迭代器operator*()中,不必返回对象的引用,它甚至可以返回新创建的对象。因此避免在Bjorn建议的迭代器对象内部有一个“虚拟”对象。

您可以查看更多here