簡體   English   中英

C ++:提升范圍迭代器指向錯誤的元素

[英]C++: boost range iterator pointing to wrong element

我遇到一個奇怪的問題。 我有一個vector<pair<bool, int>> ,我只需要從中讀取(可能寫)該對的布爾值為true的矢量元素。 我正在使用升壓范圍濾波器和反向適配器來做到這一點。

但是,我注意到適配器的順序,即是否使用反向| 過濾或過濾 反向產生不同的結果。 實際上,當我使用過濾器| 相反,當我使用迭代器到轉換后的范圍更改對的布爾值時,更改后的迭代器指向另一個向量元素。 當我使用反向|時,不會發生這種情況。 過濾。 下面是演示該問題的代碼。 任何關於為什么發生這種情況的想法都非常感謝!

#include <boost/range/adaptors.hpp>
#include <vector>
#include <utility>
#include <iostream>

using namespace boost::adaptors;

using container_type = std::vector<std::pair<bool,int>>;

struct to_include {
  bool operator()(const std::pair<bool,int>& x) {
    return x.first;
  }
};

int main() {
  container_type container;

  /* element0: 1, 1 */
  /* element1: 1, 2 */
  /* element2: 1, 3 */
  for(size_t i=0; i!=3; ++i) container.push_back(std::make_pair(true, i+1));
  container_type container_cpy = container;

  /* filter and then reverse */
  auto fr = container | filtered(to_include()) | reversed;
  auto fr_it1 = fr.begin();
  auto fr_it2 = std::next(fr_it1);
  fr_it2->first = false;

  std::cout << "FILTER AND THEN REVERSE\n";
  std::cout << fr_it2->first << " " << fr_it2->second << '\n'; /* prints (1,1) instead of (0,2) */

  /* reverse and then filter */
  auto rf = container_cpy | reversed | filtered(to_include());
  auto rf_it1 = rf.begin();
  auto rf_it2 = std::next(rf_it1);
  rf_it2->first = false;

  std::cout << "\nREVERSE AND THEN FILTER\n";
  std::cout << rf_it2->first << " " << rf_it2->second << '\n'; /* prints (0,2) */

  return 0;
}

這是一個微妙的問題。 這里的要點是,在修改fr_it2指向的元素fr_it2 ,您還隱式地修改了fr_it1因為fr是原始范圍內的惰性視圖 這意味着transformed濾波器需要重新計算。 這是一個非常不直觀的屬性,因為對於急切的STL范圍,通過迭代器進行的修改不會修改迭代器本身,但是對於惰性范圍,這不再是事實!

實際上,如果使用“新”迭代器打印整個frrf范圍,您將看到它們的內容實際上是相同的。

fr_it2->first = false;
for (auto e : fr) std::cout << e.first << e.second << ";"; // prints 13;11
...
rf_it2->first = false;
for (auto e : rf) std::cout << e.first << e.second << ";"; // prints 13;11

實時示例1 所以實際上中間元素確實被刪除了!

我認為您不應該通過迭代器將元素修改為適應范圍,而應通過迭代器將其修改為您的主容器,如下所示:

auto fr_it1 = container.begin();
...
auto rf_it1 = container_cpy.begin();

現場示例2 如果這樣做,兩種方法的結果一致,顯示為“ 0 2”。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM