2016-08-18 96 views
5

我似乎無法找到有關迭代器是否保持它們正在迭代的基礎對象的更多信息。C++迭代器是否持有對基礎對象的引用?

如果我創建一個迭代器,那麼提供它的對象超出了作用域,迭代器的存在是否阻止它被銷燬?

這裏是一個非常簡單的例子只是爲了說明的情形:

// This class takes a copy of iterators to use them later 
class Data { 
    public: 
    Data(std::vector<int>::iterator start, std::vector<int>::iterator end) 
     : start(start), 
     end(end) 
    {} 

    void show() { 
     // Use this->start and this->end for some purpose 
    } 

    private: 
    std::vector<int>::iterator start; 
    std::vector<int>::iterator end; 
}; 

Data test() { 
    std::vector<int> v{1, 2, 3}; 
    Data d(v.begin(), v.end()); 
    d.show(); // this would be ok 
    return d; 
} 

int main(void) { 
    Data d = test(); 
    d.show(); // What happens here? 
} 

在這個例子中,Data對象被存儲所述迭代器的副本,這是細用於第一show()呼叫。然而,在第二次調用show()時,提供迭代器的原始對象不再存在。

迭代器是否保持對象的狀態,直到它們全部被銷燬,或者只要原始對象超出範圍,迭代器就會失效?

這裏是one reference of many不說會發生什麼的一種方式或其他(甚至是否這樣做的結果是「不確定」。)

+7

迭代器在指針上建模。粗略地說,如果一個指針不能做一個高級的事情X,那麼迭代器也不能。 –

+0

是的,迭代器將失效,結果是未定義的。 – songyuanyao

+1

爲了解決您的具體情況:銷燬容器將使所有迭代器無效。 –

回答

5

迭代器通常不擁有它們迭代的數據,不。事實上,他們很少(如果曾經)知道擁有數據的對象的;例如,向量迭代器通常只是指針,它們不知道任何向量或其生命週期。即使那些沒有作爲指針實現的迭代器(這些指針也是大多數)可能被認爲是一種「指針」,並且這樣對待:它們很容易變成懸掛。

您的示例具有UB,因爲您將在第二次取消引用show()中的無效迭代器。

如果你的容器超出了範圍,那麼你的所有迭代器都會失效。實際上,there are all manner of reasons why an iterator may become invalidated,例如在該操作導致容量擴展時添加到向量中。

有可能找到,而不是遍歷其他地方找到(如Boost's counting iterators)一些集合迭代器種「自己」的數據,但這些都是拿C++的優勢,提供一個神奇的功能神奇的特性,不是由C++定義的迭代器的固有屬性。

2

迭代器是一般只要其原始唯一有效容器或「序列」尚未更改,因爲更改可能會導致內存重新分配和內存移動。由於發起容器中的迭代器通常是參考內存,所以容器中的更改可能使迭代器無效。

現在,一個超出範圍的容器將執行析構函數。這顯然更改容器,因此任何迭代器將在該過程中失效。

1

首先,迭代器沒有引用它迭代的對象的接口。它只實現指針語義,所以你可以把它看作抽象指針。當然,它的內部實現可能會持有指向該對象的指針,但在現實世界的實現中卻不太可能。第二,當你的容器被銷燬(當它超出範圍時),容器中的所有對象也被銷燬。因此,在容器被銷燬後,迭代器將變爲無效。在增加之後,遞減和解引用迭代器將導致未定義的行爲。