其他分享
首页 > 其他分享> > c – 使用迭代器将数组划分为大小不等的部分

c – 使用迭代器将数组划分为大小不等的部分

作者:互联网

我有一个数组,我需要分成三元素子阵列.我想用迭代器来做这件事,但是我最终迭代过了数组的末尾和segfaulting,即使我没有取消引用迭代器.给定:auto foo = {1,2,3,4,5,6,7,8,9,10};我正在做:

auto bar = cbegin(foo);

for (auto it = next(bar, 3); it < foo.end(); bar = it, it = next(bar, 3)) {
    for_each(bar, it, [](const auto& i) { cout << i << endl; });
}

for_each(bar, cend(foo), [](const auto& i) { cout << i << endl; });

现在我可以通过定义一个完成迭代器来解决这个问题:

auto bar = cbegin(foo);
auto finish = next(cend(foo), -(size(foo) % 3));

for (auto it = next(bar, 3); it != finish; bar = it, it = next(bar, 3)) {
    for_each(bar, it, [](const auto& i) { cout << i << endl; });
}

for_each(bar, finish, [](const auto& i) { cout << i << endl; });
for_each(finish, cend(foo), [](const auto& i) { cout << i << endl; });

但是,当我不取消引用迭代器时,这似乎是不必要的.为什么我不能做第一个版本?

解决方法:

这个被禁止的原因在你的其他问题Are iterators past the “one past-the-end” iterator undefined behavior?中得到了很好的解释,所以我只会提出改进的解决方案.

对于随机访问迭代器(如果使用<,则必须具有该迭代器),对于昂贵的模运算不需要任何操作. 重点是:
>当它接近结束时,它的步伐就会失败
> end() – 如果容器包含的元素太少,则stride会失败
> end() – 它总是合法的

从那里,它是简单的代数操作来改变它的步伐<结束()成法律形式(从双方减去). 最后的结果,我多次使用过:

for( auto it = c.cbegin(), end = c.cend(); end - it >= stride; it += stride )

如果内存模型是平坦的,编译器可以自由地优化回到与预先计算的end-stride * sizeof(* it)的比较–C行为的限制不适用于编译器将C转换为的基本操作.

如果您更喜欢使用命名函数而不是运算符,那么您当然可以使用std :: distance(it,end),但这对于随机访问迭代器只会有效.

要与前向迭代器一起使用,您应该使用结合增量和终止条件的东西

struct less_preferred { size_t value; less_preferred(size_t v) : value(v){} };

template<typename Iterator>
bool try_advance( Iterator& it, less_preferred step, Iterator end )
{
     while (step.value--) {
         if (it == end) return false;
         ++it;
     }
     return true;
}

通过这个额外的重载,您将获得随机访问迭代器的有效行为:

template<typename RandomIterator>
auto try_advance( RandomIterator& it, size_t stride, RandomIterator end )
     -> decltype(end - it < stride) // SFINAE
{
     if (end - it < stride) return false;
     it += stride;
     return true;
}

标签:data-partitioning,termination,c,iterator,modulo
来源: https://codeday.me/bug/20190925/1816704.html