Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何从迭代器推断连续内存_C++_Algorithm_Templates_C++17_Memcpy - Fatal编程技术网

C++ 如何从迭代器推断连续内存

C++ 如何从迭代器推断连续内存,c++,algorithm,templates,c++17,memcpy,C++,Algorithm,Templates,C++17,Memcpy,不知何故,VC++(Dinkumware)上的本机stl::copy()算法发现它可以对可复制的数据使用memcpy()。一个凡人能做到吗假设每个元素都是可复制的 随机存取迭代器是否意味着连续内存?我不清楚这个标准 那么,如果模板中只有一两个迭代器,是否可以在编译时推断底层数组可以使用memcpy()进行复制,如果可以,如何复制? 编辑-这是我的动机。我有一个移动数据块而不是复制数据块的例程。为了在数据可memmove时提高速度,我有时会调用stl::copy。我想知道这是不是唯一的办法。(作为

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

随机存取迭代器是否意味着连续内存?我不清楚这个标准

那么,如果模板中只有一两个迭代器,是否可以在编译时推断底层数组可以使用
memcpy()
进行复制,如果可以,如何复制?

编辑-这是我的动机。我有一个移动数据块而不是复制数据块的例程。为了在数据可memmove时提高速度,我有时会调用stl::copy。我想知道这是不是唯一的办法。(作为一个孩子,我总是在家里尝试这个。)

//移动一系列值
模板
内联Ptr2移动(Ptr src、Ptr end、Ptr2 dest){
使用value\u type=std::iterator\u traits::value\u type;
如果constexpr(std::是可复制的){
返回标准::副本(src、end、dest);
}否则{
while(src!=结束){
*dest=std::move(*src);
++src;++dest;
}
}
返回目的地;
}
编辑:zett42发现了这个相关的问题,我很荣幸:我无法解释我怎么会错过它

编辑更多:在浏览了许多曲折的小段落之后,我发现Dinkum使用了人群中的迭代器的秘密标记,例如_Really_triple_ptr_iterator_标记。因此前景黯淡

我的价值0.02美元:初学者犯了一个错误,把迭代器分类成一个特殊类型,而不是破坏各种特性,比如“指向连续内存”等等。。。由于random_access_迭代器是一种仅用标记表示的特殊类型,因此在不破坏遗留应用程序的情况下无法对其进行子类型化。所以委员会现在有点陷入困境。我说,是时候重新开始了

哦,好吧

随机存取迭代器是否意味着连续内存

简短回答:没有

长答案:取决于类型

例如:对于
std::vector
(使用随机访问迭代器),允许内存为所有值都位于可从
data()
方法访问的连续内存块中

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

A)不。这只意味着类型F的有效映射(迭代器+/-n)=迭代器。存在下一个/上一个…..n。这根本不意味着连续分配。(界限不适用)

B) 不,这取决于实施情况。例如,如果存在2级间接寻址,您可能不知道可能接收到哪种类型的数据结构

好消息是,你根本不必费心。在缓存和发生的分支预测之间,根本不需要对其进行优化。在运行时,缓存线将被要复制的连续内存块填满,因此速度会非常快,memmove或memcpy不会有多大帮助


现代处理器在运行时将对指令进行管道化处理,但这并不能保证什么,它们会知道指令是否连续。

std::vector的迭代器都是随机访问的,并且表示连续元素。这就是定义。请注意,对memmove的调用不一定是最快的拷贝。如果在gcc上编译std::copy时使用-O2和-march=native,则会得到更好的代码。编译器非常了解这些迭代器,并且能够识别何时使用迭代器并进行所需的优化。假设您不知道迭代器是std::vector。通过快速查看MSVC的
std::copy()
实现,没有编译器魔法来决定是否可以使用
memmove
。连续迭代器由模板元编程检测。但这是非标准化的东西,请参见。可能有内部和实现特定的类型、特征和标记,算法函数可以检查。不幸的是,它没有连续迭代器的标记。真糟糕。那么,回到问题上来,如果只有某些stl容器被保证是连续的,那么在只提供迭代器的情况下,如何对它们进行专门化?@JiveDadson-您可以研究标准,检测少数连续的容器,并创建返回编译时真值的自定义类型特征(或假值,根据容器)并决定使用这种类型的特征(不是一个很好的解决方案;我知道;但这是我心目中最好的解决方案)模板只看到迭代器,而不是容器。迭代器对它们指向的容器类型是保密的。也许它们甚至不知道。@JiveDadson-我明白了……我认为,不幸的是,你是对的:从迭代器开始,没有办法检测相应的容器;因此我没有看到解决方案。然而,不知何故,纯粹的软件至少对于指向stl::vector的指针是这样。编译器可能会生成CPU可以合理运行的可接受代码,但即使使用该代码的单个线程也无法接近内存带宽的极限。请查看C库实现的
memcpy
的汇编代码,以了解其长度它们将重叠多个操作,并有效地将位装入和移出核心。
// 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;
}