在不使用vector.end()的情况下迭代std::vector
Iterate std::vector without using vector.end()
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
) - 从函数返回一组迭代器,指定要迭代的范围
- 从函数返回一个对原始向量的引用,旁边还有一个迭代器,表示要迭代到/从中迭代的偏移量
如果不知道函数的用途,很难给出更具体的建议。我怀疑可能还有更好的方法来构建代码。
- 如果 std::vector::clear() 不是静态的,如何在没有实例的情况下调用它?
- 在没有未定义行为的情况下实现类似std::vector的容器
- 在不使用vector.end()的情况下迭代std::vector
- 如何在不使用 vector::erase() 的情况下编写自定义 Vector 方法来删除元素?
- 是否有可能在没有复制的情况下传递 std::vector<int> 作为参数来获得 std::vector<std::array<int, 3>>?
- 在不调用构造函数的情况下创建 Vector 元素
- 给定一个填充无符号字符**的 C 函数,如何在没有中间副本的情况下用数据填充 std::vector
- 如何在没有参数列表的情况下定义向量无效使用模板名称 std::vector
- 我可以在不复制的情况下将 std::vector 重新解释<char>为 std::vector<无符号字符>吗?
- 如何在不复制的情况下更新 std::unordered_map<std::string, std::vector> 中的向量<int>?
- 为什么在这种情况下使用 vector<>.push_back() 时不使用动态内存?
- 在不破坏元素的情况下调整std::vector的大小
- 如何在没有循环的情况下初始化 std::vector
- 如何在<int>不重建数组的情况下将 vector<vector> 转换为 int**?
- 为什么std::vector::template在没有调用任何复制构造函数的情况下调用析构函数
- C++ 如何在不使用 vector 的情况下从数组中删除 0 值
- 在 std::vector 上运行的多个线程:在这种情况下我需要锁定吗?
- 在这种情况下比较 std::vector 或 std::set 以获得时间复杂度 - 更有效率
- 在不丢失索引信息的情况下对std::vector进行排序
- 在这种情况下可以使用std::array(或boost::array)吗?或者我是不是一直使用std::vector和本