有人可以解释range-v3的 View 适配器drop
和drop_exactly
之间的区别吗?
我观察到的一个区别是,如果传递给这些 View 的范围内的元素数量少于 View 适配器的参数,则drop
似乎做对了,而drop_exactly
似乎调用了UB。
当参数小于传递给这些 View 的范围内的元素数量时,它们似乎都工作相同:
#include <iostream>
#include <vector>
#include <range/v3/all.hpp>
namespace rv = ranges::views;
int main()
{
std::vector<int> v { 1, 2, 3, 4, 5};
for (int i : v | rv::drop(3))
std::cout << i; // prints 45
for (int i : v | rv::drop(7))
std::cout << i; // prints nothing
for (int i : v | rv::drop_exactly(3))
std::cout << i; // prints 45
for (int i : v | rv::drop_exactly(7))
std::cout << i; // prints garbage and crashes
}
这是code。
最佳答案
从documentation中获取 drop_exactly
:
Given a source range and an integral count, return a range consisting of all but the first count elements from the source range. The source range must have at least that many elements.
虽然的文档
drop
指出:Given a source range and an integral count, return a range consisting of all but the first count elements from the source range, or an empty range if it has fewer elements.
强调添加
我猜测
drop_exactly
会避免边界检查,因此有可能以更高的性能为代价,而代价是可能会超出管道式容器的end
,而drop
显然会进行边界检查以确保您不会这样做。这与您看到的一致。如果您打印从
begin()+7
到begin()+5
的end()
(aka std::vector
)的内容,并且中止条件是使用!=
而不是<
实现的,那么您将继续打印位于 vector 分配的空间中的垃圾数据,直到出现点,您将在分配的块上运行,并且操作系统会进入并对二进制文件进行段错误处理。因此,如果您知道容器要删除的条目数量与您希望删除的条目一样多,请使用速度更快的
drop_exactly
,否则请使用drop
。
关于c++ - range-v3 views::drop和views::drop_exactly有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63402261/