簡體   English   中英

迭代std :: vector而不使用vector.end()

[英]Iterate std::vector without using vector.end()

這里的C ++新秀。 我編寫了一個從向量返回迭代器的函數,並且我想使用該迭代器從頭到尾遍歷向量。 但是,矢量迭代器的用法如下

for (auto iterator = vec.begin(); iterator != vec.end(); iterator ++) {
// do something here
}

這意味着我還需要一個vec.end()才能工作。 無論如何,像我通常在python中一樣,我只能使用vec.begin()來遍歷向量

for value in some_iterator:
# do something

編輯:一些不相關的更新:

我看到一些關於我的python迭代器與可迭代的評論。 實際上可以以這種方式使用迭代器(至少在Python 3中如此)。 例如:

some_list = [1,2,3,4]
some_iterator = iter(some_list)
for value in some_iterator:
    print(value)

C ++不是Python。 std::vector::iterator s的需要來表示的范圍(開始和一個過去的端部)。 如果你只有一個迭代器 ,還有什么可以放心地用它做(除了它自身比較,這是空洞地true )。

您會混淆Python 可迭代的python概念,它是一個值序列。 這與Python 迭代器不同 ,后者是一個具有next() (Python 3中為__next__()的對象,該對象返回下一個值或引發StopIteration

for value in some_iterable:
    #do something here

大致對應

_iter = some_iterable.__iter__()
while True:
    try
        value = _iter.__next__()
    except StopIteration:
        break;
    #do something here

您可能想要一個范型語句

for (auto val : vec){
    // do something here
}

大致對應

{
    auto && __range = vec; 
    for (auto __begin = begin(__range), __end = end(__range);  __begin != __end; ++__begin) { 
        auto val = *__begin; 
        // do something here
    } 
} 

(在兩個版本中,前導_的局部變量實際上都不存在,名稱是說明性的)

C ++迭代器從移動( ++it等)中分離出返回值( *itit-> ); 從停止( it != end ),在那里end一個過去的最后一個元素。 Python迭代器在next()所有操作。

正如其他人已經指出的那樣:

for value in some_iterator:
# do something

是不正確的:您使用數組的內部__iter__迭代器在數組中或更普遍地在“ 可迭代 ”中進行迭代。 因此更正確:

for value in some_iterable:
# do something

python中的Iterable是C ++中的“容器”。 std::vector是一個容器。

我認為您有兩種選擇:

  • 如果您想擁有完整的容器(“從頭到尾”,那么我想是這樣),只需返回它即可。 如果函數退出后生命仍然延續,則可以通過引用返回它:實際上,在python數組中是通過引用復制的,所以這是等效的。 但是,如果它是一個臨時向量,則可以按值返回它,但不必擔心會被復制:使用現代C ++和std :: move運算符不會發生這種情況。

“老方法”是通過引用該函數傳遞一個空向量,然后讓該函數填充該向量。

但是,我通常不喜歡將std::pair用於此類操作,而是針對特定目的偽造我的臨時類型。

例如,這可能是您的函數的簽名:

template<typename TYPE>
struct GetRangeResult {
  std::vector<TYPE>::const_iterator begin;
  std::vector<TYPE>::const_iterator end;
};

template<typename TYPE>
GetRangeResult<TYPE> GetRange(/* your args */) {
  GetRangeResult<TYPE> result;
  // the method here fills result.begin and result.end
  return result;
}

您將使用它:

auto range = GetRange(/* your args */);
for (auto it=range.begin; it!=range.end; ++it) {
  ...
}

同樣,如果向量在GetRange()函數中是臨時的,則無法執行此操作。

我編寫了一個從向量返回迭代器的函數,並且我想使用該迭代器從頭到尾遍歷向量。

您需要2個迭代器才能遍歷一個容器-起始迭代器和終止迭代器。 例如,更改您的函數以返回std::pair迭代器,而不是單個迭代器,則可以進行迭代,例如:

template<typename Container>
std::pair<Container::iterator, Container::iterator> func(Container &c) {
    return std::make_pair(c.begin(), c.end());
}

auto p = func(vec);
for (auto iter = p.first; iter != p.second; ++iter) {
    // do something here
}

反正我只能使用vec.begin()遍歷向量

不。沒有第二個迭代器,您將不知道何時停止迭代。

就像我通常在python中所做的那樣

與此最接近的是基於范圍的for循環,但是它需要訪問向量本身,它使用迭代器手動進行(循環內部為您使用了迭代器):

for (auto &elem : vec) {
    // do something here
}

無法從迭代器獲取對原始容器的引用。 這意味着,如果您有一個將迭代器返回到向量中點的函數,則除非您知道它來自哪個向量,否則實際上是無用的。

您可以選擇:

  1. 僅在可以訪問要操作的向量時使用該函數(類似於std::find類的用法)。
  2. 從函數中返回一組迭代器,這些迭代器指定要迭代的范圍。
  3. 從函數返回對原始矢量的引用以及表示要迭代的偏移量的迭代器。

在不知道函數目的的情況下,很難給出更具體的建議。 我懷疑構造代碼可能更好。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM