如何从迭代器中推导出连续的内存

时间:2017-12-04 21:26:02

标签: c++ algorithm templates c++17 memcpy

不知何故,VC ++上的本地stl::copy()算法(Dinkumware)发现它可以对可以轻易复制的数据使用memcpy()。凡人都有可能做到这一点吗? - 假设每个元素都是__ivivially_copyable。

random_access_iterator是否意味着连续的内存?标准对我来说并不清楚。

因此,如果模板中的所有内容都是一个或两个迭代器,是否可以在编译时推断出可以使用memcpy()复制基础数组,如果是,如何?

编辑 - 这是我的动力。我有一个例程,它移动一个数据块而不是复制它。为了在数据可记忆时获得速度,我有时会调用stl :: copy。我想知道这是否是唯一的方法。 (作为一个孩子,我总是在家里尝试这个。)

// Move a range of values
template<class Ptr, class Ptr2>
inline Ptr2 move(Ptr src, Ptr end, Ptr2 dest) {
    using value_type = std::iterator_traits<Ptr>::value_type;
    if constexpr (std::is_trivially_copyable_v<value_type>) {
        return std::copy(src, end, dest);
    } else {
        while (src != end) {
            *dest = std::move(*src);
            ++src; ++dest;
        }
    }
    return dest;
}

编辑:感谢zett42发现这个相关问题:Contiguous iterator detection我无法解释我是如何错过它的。

编辑更多:在经历了许多曲折的小段落之后,我发现Dinkum使用秘密标签用于与人群中的迭代器,例如_Really_trivial_ptr_iterator_tag。所以前景看起来很暗淡。

我的0.02美元价值:初学者的错误是让iterator_category成为ad-hoc类型而不是破坏各种特征,比如“points_into_contiguous_memory”等等......因为random_access_iterator是一个仅用标签表示的ad-hoc类型,它不能在不破坏遗留应用程序的情况下进行子类型化。所以委员会现在有点卡住了。我说,是时候重新开始了。

哦,好吧。

2 个答案:

答案 0 :(得分:2)

  

random_access_iterator是否意味着连续的内存?

简答:不。

长答案:取决于类型。

示例:对于std::vector(使用随机访问迭代器),它被授予内存所有值都在一个连续的内存块中,可以从data()方法访问。

对于std::deque(也使用随机访问迭代器),您知道内存区域被分成块(std::deque被设计为在中间有效插入/移除元素)所以不可能记忆是连续的。

答案 1 :(得分:1)

A)不。它只是意味着F(迭代器+/- n)= iterator.next/prev.....n的有效映射存在。这并不意味着连续的分配。 (界限确实适用)

B)否。这取决于实施情况。例如,如果存在2级间接,您可能不知道可能接收何种数据结构。

好消息?,你根本不需要打扰。在缓存和发生的分支预测之间,您根本不需要对其进行优化。在运行期间,缓存行将填充您要复制的连续内存块,因此它将非常快,memmove或memcpy将无济于事。

对于在运行时管理您的指令的现代处理器,您不能保证很多,并且他们会知道它是否是连续的。