2013-08-16 51 views
3

許多標準庫容器的操作都接受迭代器指定的範圍。例如,std::list::assign(InputIterator first, InputIterator last)如何檢查迭代器指定的範圍是否有效?

但是,因爲這些操作中的很多不會拋出異常,所以如果[first,last)指定的範圍無效,則會導致未定義的行爲。

那麼有效範圍?我認爲這意味着first之前或等於last在容器中,因爲當我另外嘗試(即first之後來到last),程序的執行會掛起。

例如:

std::list.assign(container.begin(), container.end()); // valid range 
std::list.assign(container.end(), container.begin()); // invalid range 
用的有效範圍是什麼假設

現在,我們怎麼能檢查的範圍是有效的?

我想出了一個幫助函數,它在到達容器末尾之前檢查first是否等於last。如果屬實,那麼first不會在last之後出現,因此該範圍有效。

template <typename Iterator> 
bool isValidRange(Iterator first, Iterator last, Iterator end) 
{ 
    for (; first != end; ++first) 
    if (first == last) return true; 
    return false; 
} 

這不是很方便,因爲除了指定範圍的迭代器之外,您還必須將它傳遞給容器的末端。

這是正確的嗎?有一個更好的方法嗎?

+0

要檢查範圍是否有效,請增加第一個迭代器直到它等於第二個;那麼你知道它是有效的。如果它不等於第二個,那麼範圍是無效的。 –

+0

更嚴重的一點是:不要將範圍和容器等同起來。容器是創建範圍的一種方式,但它們不是唯一的方法。例如,輸入流中的迭代器不是來自容器。 –

+0

@PeteBecker在這種情況下,爲什麼像'list_a.assign(list_b.end(),list_b.begin());'掛起程序? 'std :: list :: end'和'std :: list :: begin'返回一個雙向迭代器,所以第一個迭代器最終會到達第二個迭代器,這意味着它應該根據你的描述是有效的。 – Dennis

回答

7

如何檢查範圍是否有效?

你不行。你的函數不能保證範圍是有效的,只有最後一個可以從第一個到達。這是兩個不同的事情(對於一個簡單的例子,考慮一個迭代器到隨後被重新分配的向量中)。標準沒有允許您檢查範圍是否有效的機制。就像您在取消引用它之前無法知道指針是有效的一樣。

需要注意的是,微軟提供了一個函數來檢查指針是否有效,並徹底解決了所有使用它的人。雷蒙德表示,它應該被命名爲CorruptMemoryIfPossible。

+5

+1 Ha microsoft – aaronman

+0

我發現了Raymond Chen的帖子:http://blogs.msdn.com/b/oldnewthing/archive/2006/09/27/773741.aspx。很好的閱讀。 TL; DR在給出無效輸入時應該會崩潰。 – Dennis