我想将矢量的一部分复制到自身,例如
size_t offset; /* some offset */
std::vector<T> a = { /* blah blah blah */};
std::copy(a.begin() + offset, a.begin() + (offset*2), a.begin());
但是,我担心这种方法的表现。当有问题的类型允许它时,我希望将其归结为单个memmove
(或等效的),但是当给出非平凡可复制类型时,仍然可以按照预期的方式运行。
当模板类型T
可以轻易复制时(特别是int64_t
如果重要),这会导致一个memmove
长度为sizeof(T) * offset
,或{{1 } offset
长度memmove
?我认为后者会显着降低性能,因为它需要许多单独的内存读取。或者我应该假设缓存会使这些情况下的性能在相对较小的偏移量(&lt; 100)下有效等效?
如果模板类型sizeof(T)
不可以轻易复制,是否可以保证对复制赋值运算符T
进行offset
个不同的调用,或者会发生什么奇怪的事情?
如果T::operator=
没有产生我正在寻找的结果,是否有一些替代方法可以满足我的性能限制,而无需为所有类型编写复制代码的模板特化问题?
编辑:GCC 5.1.0,使用-O3
进行编译答案 0 :(得分:3)
除了明确出现在标准中的保证之外,无法保证标准库函数的实现方式:
有效调用的可观察效果,以及
空间和时间复杂度(在这种情况下:要复制的对象数量严格为线性,假设复制对象为O(1))。
因此std::copy
可能会或可能不会等同于memmove
。它可以在一个简单的循环中进行逐个元素的复制。或者它可能会展开循环。或者它可能会调用memmove
。或者它可能会找到一个更快的解决方案,基于编译器关于数据类型对齐的知识,可能使用矢量化优化。
&lt; rant&gt;与看似流行的观点相反,标准C ++库的作者并没有放慢你的代码的阴谋,也没有那些有几个月编码经验的人无能为力可以轻松生成更快的代码。对于特定用例,您可能能够利用您对移动数据的了解来找到更快的解决方案,但总的来说 - 特别是在没有分析实际代码的情况下 - 您最好的选择是假设标准库作者是优秀的程序员致力于使您的程序尽可能高效。 &LT; /咆哮&GT;
答案 1 :(得分:0)
如果问题与标准有关,答案是“任何事情都可能发生”。可能memmove()
,可能不会。另一方面,如果问题是关于特定的实现,而不是你不应该问,而是检查你的实现。
在我的实施中,这是memmove()
电话。
顺便说一下,很难想象实现offset
内存移动。它可以是memmove()
的单个调用,也可以是逐个元素的循环复制。致电memmove()
毫无意义。