2010-10-29 65 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