gpt4 book ai didi

c++ - 为什么在使用 `std::views::reverse` 时对过滤函数进行了多余的调用?

转载 作者:行者123 更新时间:2023-12-03 23:58:33 27 4
gpt4 key购买 nike

我试图了解通过管道运算符( View /适配器)传递时对过滤器函数的调用顺序。我看到的结果根本不直观。虽然可能有原因,但如果有人能解决这个问题,我将不胜感激。如果您可以指向 cppreference.com 上的正确文档,也一样。 .

#include <vector>
#include <ranges>
#include <iostream>

int main() {
const auto vec = std::vector{1,2,3,4,5,6};
auto filter = [](const auto f) {
std::cout << "f = " << f << ", ";
return f % 2 == 0;
};

std::cout << std::endl;
for (auto v : vec
| std::views::reverse
| std::views::filter(filter)
| std::views::take(2)
| std::views::reverse)
{
std::cout << std::endl << "v = [" << v << "]" << std::endl;
}
}
实际结果:
f = 6, f = 5, f = 4, f = 3, f = 2, f = 3, f = 4, 
v = [4]
f = 3, f = 4, f = 5, f = 6,
v = [6]
f = 5, f = 6,
预期结果:
f = 6, f = 5, f = 4, f = 3, f = 2, f = 1, 
v = [4]
v = [6]
这是 godbolt上面代码的示例。这里是 some more code ,我试着分解一下来理解。但没有什么是显而易见的。

最佳答案

所讨论的基于范围的 for 循环可以重写为

auto&& range = vec
| std::views::reverse
| std::views::filter(filter)
| std::views::take(2)
| std::views::reverse;

auto begin = range.begin();
auto end = range.end();

for (; begin != end; ++begin) {
auto v = *begin;
std::cout << std::endl << "v = [" << v << "]" << std::endl;
}
  • range 的初始化器只构建 View 。什么都不输出。
  • range.begin()返回 reverse_iterator谁的base()是底层 View 末尾的迭代器。为了找到底层 View 的结尾,5次调用filter制作(对应于 f = 6, f = 5, f = 4, f = 3, f = 2, )。
  • range.end()返回 reverse_iterator谁的base()是底层 View 开头的迭代器。开头filter_view已缓存。不接电话 filter制作。
  • begin != end返回真。
  • *begin递减底层基迭代器的拷贝,以便访问反向范围的第一个元素。这导致接下来的 2 次调用 filter (对应于 f = 3, f = 4, )。
  • 输出第一个元素的值。 ( v = [4] )
  • ++begin递减基础基迭代器。 ( f = 3, f = 4, )
  • begin != end返回真。
  • *begin递减底层基迭代器的拷贝以访问第二个元素。 ( f = 5, f = 6, )
  • 输出第二个元素的值。 ( v = [6] )
  • ++begin递减基础基迭代器。 ( f = 5, f = 6, )
  • begin != end返回假。
  • 关于c++ - 为什么在使用 `std::views::reverse` 时对过滤函数进行了多余的调用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66219755/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com