C++菜鸟。我写了一个函数,从向量返回迭代器,我想使用这个迭代器从头到尾迭代向量。然而,向量迭代器的使用方式与类似
for (auto iterator = vec.begin(); iterator != vec.end(); iterator ++) {
// do something here
}
这意味着我还需要一个vec.end()来实现这一点。不管怎样,我只能使用vec.begin()来迭代一个向量,就像我在python 中经常做的那样
for value in some_iterator:
# do something
编辑:一些无关的更新:
我看到一些关于我的python迭代器与iterable的评论。迭代器确实可以这样使用(至少在Python3中是这样)。例如:
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()
(Python3中的__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()
中完成所有任务。
正如其他人已经指出的那样:
for value in some_iterator:
# do something
不正确:您在数组中进行迭代,或者更一般地说,在"可迭代"中,通过使用它的内部__iter__
迭代器进行迭代。所以它更正确:
for value in some_iterable:
# do something
python中的可伸缩性是C++中的"容器"。std::vector
是一个容器。
我认为你有两个选择:
- 如果你想拥有完整的容器("从头至尾",所以我想是这样),只需返回它。如果函数退出后它的寿命继续,你可以通过引用返回它:事实上,在python中,数组是通过引用复制的,所以这是等效的。然而,如果它是一个临时向量,您可以按值返回它,但不要担心它会被复制:使用现代C++和std::move运算符,这是不会发生的
"旧方法"是通过引用函数来传递一个空向量,并让函数填充该向量。
- 如果你想返回一个范围,你可以返回一对迭代器。例如,您可以模拟std::multimap<>::equal_range()返回
然而,我通常不喜欢将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()
函数中是临时的,则不能执行此操作。
我写了一个函数,从向量返回迭代器,我想使用这个迭代器从头到尾迭代向量。
您需要两个迭代器来遍历容器——起始迭代器和结束迭代器。例如,更改函数以返回迭代器的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
}
没有办法从迭代器获取对原始容器的引用。这意味着,如果你有一个函数,比如说,将迭代器返回到向量的中点,那么它实际上是无用的,除非你知道它来自哪个向量。
您的选择是:
- 只有当您可以访问正在操作的向量时才使用该函数(用法类似于
std::find
) - 从函数返回一组迭代器,指定要迭代的范围
- 从函数返回一个对原始向量的引用,旁边还有一个迭代器,表示要迭代到/从中迭代的偏移量
如果不知道函数的用途,很难给出更具体的建议。我怀疑可能还有更好的方法来构建代码。