首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >迭代std::向量而不使用vector.end()

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

Stack Overflow用户
提问于 2018-07-30 15:40:50
回答 4查看 1.2K关注 0票数 0

C++新手来了。我编写了一个函数,它从一个向量返回一个迭代器,我想使用这个迭代器从头到尾遍历这个向量。但是,向量迭代器的使用方式如下

代码语言:javascript
运行
复制
for (auto iterator = vec.begin(); iterator != vec.end(); iterator ++) {
// do something here
}

这意味着我还需要一个vec.end()才能工作。无论如何,我是否只能使用vec.begin()来迭代一个向量,就像我在python中通常所做的那样

代码语言:javascript
运行
复制
for value in some_iterator:
# do something

编辑:一些不相关的更新:

我看到了一些关于python迭代器和迭代器的注释。迭代器确实可以以这种方式使用(至少在Python 3中是这样)。例如:

代码语言:javascript
运行
复制
some_list = [1,2,3,4]
some_iterator = iter(some_list)
for value in some_iterator:
    print(value)
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-07-30 16:23:19

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

您需要两个迭代器来迭代一个容器--起始迭代器和结束迭代器。例如,将函数更改为返回迭代器的std::pair,而不是单个迭代器,然后可以迭代,例如:

代码语言:javascript
运行
复制
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循环,但这需要访问向量本身,它使用手动迭代器(循环在内部使用迭代器):

代码语言:javascript
运行
复制
for (auto &elem : vec) {
    // do something here
}
票数 1
EN

Stack Overflow用户

发布于 2018-07-30 15:50:33

C++不是Python。需要一对std::vector::iterators来表示一个范围(开始和结束后的一个)。如果您只有一个Iterator,那么您就无法安全地使用它(除了将它与其自身进行比较,这是真空的true)。

您混淆了可迭代的python概念,它是一个值序列。这与Python 迭代器不同,后者是一个具有next() ( Python 3中的__next__())的对象,返回下一个值或抛出StopIteration

代码语言:javascript
运行
复制
for value in some_iterable:
    #do something here

它大致相当于

代码语言:javascript
运行
复制
_iter = some_iterable.__iter__()
while True:
    try
        value = _iter.__next__()
    except StopIteration:
        break;
    #do something here

你可能想要一个ranged for语句

代码语言:javascript
运行
复制
for (auto val : vec){
    // do something here
}

它大致相当于

代码语言:javascript
运行
复制
{
    auto && __range = vec; 
    for (auto __begin = begin(__range), __end = end(__range);  __begin != __end; ++__begin) { 
        auto val = *__begin; 
        // do something here
    } 
} 

(在这两个版本中,带有前导_的局部变量实际上并不存在,名称是解释性的)

C++迭代器将从移动(++it等)中返回的值(*itit->)和从from (it != end)中分离出来,其中end指向最后一个元素。Python迭代器在next()中完成了所有这些工作。

票数 7
EN

Stack Overflow用户

发布于 2018-07-30 16:30:51

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

代码语言:javascript
运行
复制
for value in some_iterator:
# do something

是不正确的:通过使用数组的内部可迭代迭代器,在数组中迭代,或者更一般地在“__iter__”中迭代。所以这更正确:

代码语言:javascript
运行
复制
for value in some_iterable:
# do something

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

我想你有两个选择:

  • 如果您想要完整的容器(“从头到尾”,所以我想是这样的),只需返回它。如果函数退出后它的生命继续,您可以通过引用返回它:实际上,在python数组中是通过引用复制的,所以这是等价的。但是,如果它是一个临时向量,您可以按值返回它,但不要担心它会被复制:对于现代的C++和std::move操作符,这是不会发生的。

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

  • 如果要返回范围,可以返回一对迭代器。例如,您可以模拟范围()返回的内容。

然而,我通常不喜欢在这类操作中使用std::pair,而是为了特定的目标而伪造临时类型。

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

代码语言:javascript
运行
复制
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;
}

你会用它:

代码语言:javascript
运行
复制
auto range = GetRange(/* your args */);
for (auto it=range.begin; it!=range.end; ++it) {
  ...
}

同样,如果向量在GetRange()函数中是临时的,则不能这样做。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51597626

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档