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

时间:2018-07-30 15:40:51

标签: c++ iterator

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)

4 个答案:

答案 0 :(得分:6)

C ++不是Python。需要std::vector::iterator来表示范围(开始和结束后一个)。如果您只有一个 Iterator ,那么您可以放心使用 (除了将其与自身进行比较之外,通常都是true)。

您在混淆Python iterable的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等)中分离出返回值(it->++it);从停止(it != end开始,end指向最后一个元素一个。 Python迭代器可在next()中完成所有工作。

答案 1 :(得分:2)

正如其他人已经指出的那样:

v.getId();

是不正确的:您正在使用数组的内部Buttons迭代器在数组中或更普遍地在“ iterable”中进行迭代。所以更正确:

for value in some_iterator:
# do something

Python中的可迭代项在C ++中是“容器”。 __iter__是一个容器。

我认为您有两种选择:

  • 如果您想拥有完整的容器(“从头到尾”,那么我想是这样),只需返回它即可。如果函数退出后生命仍然延续,则可以通过引用返回它:实际上,在python数组中是通过引用复制的,所以这是等效的。但是,如果它是一个临时向量,则可以按值返回它,但不必担心会被复制:对于现代C ++和std :: move运算符,这种情况将不会发生。

“老方法”是通过引用该函数传递一个空向量,然后让该函数填充向量。

但是我通常不喜欢使用for value in some_iterable: # do something 进行此类操作,而是为特定目的伪造我的临时类型。

例如,这可能是您的函数的签名:

std::vector

,您将使用它:

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; } 函数中是临时的,则同样无法执行。

答案 2 :(得分:1)

  

我编写了一个从向量返回迭代器的函数,我想使用此迭代器从头到尾遍历向量。

您需要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
}

答案 3 :(得分:0)

无法从迭代器获取对原始容器的引用。这意味着,如果您有一个将迭代器返回到向量中点的函数,则除非您知道它来自哪个向量,否则实际上是无用的。

您可以选择以下任一方式:

  1. 仅在访问要操作的向量时使用该功能(类似于std::find之类的用法)。
  2. 从函数中返回一组迭代器,这些迭代器指定要迭代的范围。
  3. 从函数中返回对原始矢量的引用,并带有一个迭代器,该迭代器表示要迭代的偏移量。

在不知道函数目的的情况下,很难给出更具体的建议。我怀疑在结构代码方面可能会更好。