c++ - range-v3 views::drop和views::drop_exactly有什么区别?

标签 c++ range-v3

有人可以解释range-v3的 View 适配器dropdrop_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()+7begin()+5end()(aka std::vector)的内容,并且中止条件是使用!=而不是<实现的,那么您将继续打印位于 vector 分配的空间中的垃圾数据,直到出现点,您将在分配的块上运行,并且操作系统会进入并对二进制文件进行段错误处理。
因此,如果您知道容器要删除的条目数量与您希望删除的条目一样多,请使用速度更快的drop_exactly,否则请使用drop

关于c++ - range-v3 views::drop和views::drop_exactly有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63402261/

相关文章:

c++ - 范围修剪 View 实现不适用于反向 View

c++ - 为什么我的代码会产生段错误?

当几乎相同的函数工作时,C++ OIS 段错误

c++ - `closed_iota`和 `iota`之间的区别?

c++ - Range v3 中的 Readable 概念到底是什么?

c++ - 我可以通过管道传输 range-v3 累积吗?

c++ - 解析这个 json 的正确方法是什么?使用 ArduinoJson

c++ - Gstreamer 元素在 C 程序中不可用,但使用 gst-tools 确实可用

c++ - 初始化一个本身合法的引用成员?

c++ - 作为数据成员的范围 View