2010-11-09 117 views
0

我有一个容器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); 
    } 

回答

1

您可以使用<iterator>std::make_move_iterator来包装你的迭代成move_iterator。这个迭代器将取消引用其基本迭代器的结果,从而允许将其移动到别处。

// 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); 

那么,你觉得清洁剂是你的。 (第一个,对我来说)

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循环在这方面应该更好。