Ale*_*104 3 c++ c++20 std-ranges
#include <iostream>
#include <vector>
#include <ranges>
int main()
{
std::vector<int> ints {1, 2, 3, 4, 5};
auto isEven = [] (const auto& element)
{
return element % 2 == 0;
};
auto even = ints | std::views::filter(isEven);
for (auto& element : even)
{
++element;
}
for (const auto& element : ints)
{
std::cout << element << "\n";
}
std::cout << "\n\n";
// Interesting things start further...
for (auto& element : even)
{
++element;
}
for (const auto& element : ints)
{
std::cout << element << "\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出:
1
3
3
5
5
1
4 // Interesting...
3
5
5
Run Code Online (Sandbox Code Playgroud)
您注意到4第二个输出中的这一秒了吗?它是怎么到那里的?似乎发生的原因是even.begin()在视图的第一次迭代期间已被缓存,并且视图不再正确,因为它始终以相同的元素开头,无论 的实际值如何*even.begin()。
这是否意味着视图不应该被重用?但为什么要缓存呢?
以这种方式修改a的元素filter_view被指定为UB。
\n\n允许修改 a 表示的元素
\nfilter_\xc2\xadview\xe2\x80\x8b::\xe2\x80\x8biterator,但如果结果值不满足过滤谓词,则会导致未定义的行为。
视图可以重复使用,但是当然你需要遵守规则。
\n
even.begin()在视图的第一次迭代期间已被缓存,并且视图不再正确
是的,你理解正确——这就是filter_view工作原理。
这是否意味着视图不应该被重用?但为什么要缓存呢?
只要不修改视图的结果,视图就始终可以重复使用。这就是实施缓存的原因。您也可以修改结果,但必须小心。对于涉及谓词的视图(就像take_view这样做),您的修改不允许更改谓词的结果。在您的示例中,如果您的修改是:
for (auto& element : even)
{
element+=2;
}
Run Code Online (Sandbox Code Playgroud)