2010-11-09 154 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循環在這方面應該更好。