是對輸入迭代器這個正確的行爲,關於訪問的最後一個項目:得到最後一個項目
for(i=being();i!=end();i++){}
std::string s = i->toString();
return s;
還是應該拋出一個異常,如果我嘗試這樣做?
我的迭代器利用了兩個C函數調用:getFirst(...)和GetNext(...)
是對輸入迭代器這個正確的行爲,關於訪問的最後一個項目:得到最後一個項目
for(i=being();i!=end();i++){}
std::string s = i->toString();
return s;
還是應該拋出一個異常,如果我嘗試這樣做?
我的迭代器利用了兩個C函數調用:getFirst(...)和GetNext(...)
不,這也不行,你會被提領end()
和調用未定義的行爲。考慮:
int main()
{
int i = 0;
for (; i < 42; ++i) ;
std::cout << i; // prints 42, did you expect 41?
}
除非你在這種情況下實現了你的迭代器類來做一些明智的事情。然而,這對於標準庫迭代器來說並不好。
這不是一個正確的行爲。 C++中的標準約定是,end()
應指向最後一項之外的地方。解除引用會導致未定義的行爲(C++ 11§24.2.2/ 5)。
你可以讓你自己的迭代器原諒解引用end()
並利用這個,但它偏離了標準的做法,並使人們很難理解你的代碼。我建議你拋出異常而不是返回最後一項。
在標準C++,如果你已經是不可再現的輸入迭代器,這是不可能的,除非你每次都提取到「得到最後一個項目」:
auto it = begin();
auto val;
while (it != end()) {
val = *it;
++ it;
}
return val;
但是,如果你可以創建一個向前迭代器,那麼你可以使用
auto iter = begin();
decltype(iter) last_iter;
while (true) {
last_iter = iter++;
if (iter == end())
break;
}
return last_iter;
或者,如果你創建輸入迭代兩次便宜,你可以做迭代兩次:
auto dist = std::distance(begin(), end());
auto last_iter = begin();
std::advance(last_iter, dist - 1);
return last_iter;
+1今天所有的upvoters在哪裏? :P – jrok
就stl容器而言,這是不正確的行爲。
端()
返回一個迭代參照過去最端部元件在列表 容器。
這意味着你的循環後,我不指向一個正確的對象(而不是最後一個元素),而是指向一個特殊的定義的最終值,這將導致訪問衝突調用i->的toString()。
行爲是未定義的,在實現迭代器時無需做任何事情(甚至不需要引發異常)。在實施InputIterators,你只需要執行的操作
iter == iter2
,iter != iter2
*iter
,iter->...
++iter
,(void)iter++
*r++
其中,只有最後一個是很難(當你將迭代器移到時,你必須返回前一個位置的數據下一個)。它通常由一個代理來實現,它記住了舊數據。
這應該工作,除了你拼寫'開始'錯誤。 – Daniel
@RedX,Daniel:這是錯誤的,'i == end()'在循環結束後。 – kennytm
@血液我正在移動到最後,然後訪問最後一個項目。由於迭代器只有函數的第一個和下一個我不能跳到最後一步 – Baz