我有一个容器std :: vector,我想有效地将它拆分成子范围,每个子项中包含x个项目。不需要原始容器,因此应移动项目而不将其复制到子范围中。
我已经设法使用复制进行拆分,但是我不确定如何使用移动分配来进行拆分?
range.insert(range.end(), new_items.begin(), new_items.end());
while(range.size() >= x)
{
sub_ranges.push_back(std::vector<int>(range.begin(), range.begin() + x));
range = std::vector<int>(range.begin() + x, range.end());
}
编辑:
一些进步......仍然没有完全存在,而且有点难看
while(range.size() >= x)
{
std::vector<short> sub_range(x); // Unnecessary allocation?
std::move(range.begin(), range.begin() + x, sub_range.begin());
sub_ranges_.push_back(std::move(sub_range));
std::move(range.begin() + x, range.end(), range.begin());
range.resize(range.size() - x);
}
答案 0 :(得分:3)
一个问题:你有没有听说过View
概念。
我们的想法是,不是实际移动数据,而是创建一个“视图”(代理模式)来限制/改变您对它的看法。
例如,对于范围,一个非常简单的实现是:
template <typename Iterator>
struct Range
{
Iterator mBegin, mEnd;
};
Boost.Range
提供了一个胖版本,有很多东西。
在这种情况下,优点很多。其中:
vector
,因此更好的记忆位置以下是使用此方法的split
:
typedef Range<std::vector<int>::iterator> range_type;
std::vector<range_type> split(std::vector<int> const& range, size_t x)
{
std::vector<range_type> subRanges;
for (std::vector<int>::iterator it = range.begin(), end = range.end();
it != end; it += std::min(x, (size_t)std::distance(it,end)))
{
subRanges.push_back(range_type(it,end));
}
return subRanges;
}
当然,这只有在你可以保留range
对象时才有效。
关于你的原始算法:在这里使用while
循环是假的,并迫使你使用比move
更多的for
s。我制作的{{1}}循环在这方面要好得多。
答案 1 :(得分:1)
您可以使用std::make_move_iterator
中的<iterator>
将迭代器包装到move_iterator
中。这个迭代器将std::move
解除引用其基础迭代器的结果,允许将其移动到其他地方。
// assuming I understand your code, which I don't
range.insert(range.end(), new_items.begin(), new_items.end());
while(range.size() >= x)
{
auto first = std::make_move_iterator(range.begin());
auto last = std::make_move_iterator(range.begin() + x);
sub_ranges.push_back(std::vector<int>(first, last));
range = std::vector<int>(range.begin() + x, range.end());
}
编辑:就像您找到的那样,std::move()
和make_move_iterator
之间存在映射:
std::move(first, last, out); // is the same as
std::copy(std::make_move_iterator(first), std::make_move_iterator(last), out);
所以你发现清洁剂取决于你。 (第一个,对我来说。)