在向量内移动项目的最有效方法是什么?
我见过一些特殊情况,可以使用 std::rotate
或与其中一种搜索算法结合使用,但通常:当一个人有 N 个项目的向量并想要编写如下函数时
void move( int from, int count, int to, std::vector<int>& numbers );
:一直在考虑创建一个新的向量+ std::copy 或插入/擦除的组合,但我不能说我最终得到了一些漂亮而优雅的解决方案。
I've seen some special cases where std::rotate
could be used or a combination with one of the search algorithms but generally: when one has a vector of N items and wants to code function like:
void move( int from, int count, int to, std::vector<int>& numbers );
I've been thinking about creation of a new vector + std::copy
or combination of insert/erase but I can't say I ended up with some nice and elegant solution.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
在得出任何结论之前先进行分析总是很重要的。
vector
数据内存的连续性可能会提供基于节点的容器所没有的显着缓存优势。因此,也许您可以尝试直接方法:在 C++11 中,您可以将第一行和第三行中的迭代器包装到
std::make_move_iterator
中。(要求
dst
不能位于[start, start + length)
范围内,否则问题无法明确定义。)It's always important to profile before jumping to any conclusions. The contiguity of
vector
's data memory may offer significant caching benefits that node-based containers don't. So, perhaps you could give the direct approach a try:In C++11, you'd wrap the iterators in the first and third line into
std::make_move_iterator
.(The requirement is that
dst
not lie within[start, start + length)
, or otherwise the problem is not well-defined.)根据向量的大小和涉及的范围,这可能比执行复制/擦除/插入更便宜。
(这假设范围有效并且不重叠。)
Depending on the size of the vector and the ranges involved, this might be less expensive than performing copy/erase/insert.
(This assumes the ranges are valid and they don't overlap.)
C++11 之前的版本(尽管以下内容仍然有效),对于专门化/重载
std::swap
的包含类型,您可以获得更高效的“移动”。要利用这一点,您需要执行类似的操作。如果 Foo 有移动运算符但没有专门的
swap
,那么上面的内容也可能为 C++11 提供良好的结果。如果
Foo一些巧妙的序列类型可能效果更好> 没有移动语义或其他优化的
swap
另请注意,如果上述内容在函数中
,那么您可能能够执行整个操作 无需复制任何内容,即使在 C++98 中要实现此功能,您需要经过value 和 not 通过引用,这违背了传统的首选通过引用传递的智慧。
Pre-C++11 (although the following remains valid) you can get more efficient "moves" for contained types which specialise/overload
std::swap
. To take advantage of this, you would need to do something likeThe above may also give good results for C++11 if Foo has a move-operator but hasn't specialised
swap
.Linked lists or some clever sequence type might work out better if
Foo
doesn't have move semantics or an otherwise-optimisedswap
Note also that if the above is in a function
then you might be able to perform the whole operation without copying anything, even in C++98 but for this to work you will need to pass by value and not by reference, which goes against the conventional prefer-pass-by-reference wisdom.