c++ - 反转按需迭代器

标签 c++ stl iterator reverse-iterator

我有一个迭代器 DataIterator,它按需生成值,因此取消引用运算符返回一个 Data,而不是 Data&。我认为这是一件好事,直到我尝试通过将数据包装在 reverse_iterator 中来反转数据 DataIterator。

DataCollection collection

std::reverse_iterator<DataIterator> rBegin(iter) //iter is a DataIterator that's part-way through the collection
std::reverse_iterator<DataIterator> rEnd(collection.cbegin());

auto Found = std::find_if(
    rBegin, 
    rEnd,
    [](const Data& candidate){
        return candidate.Value() == 0x00;
});

当我运行上面的代码时,它从来没有找到一个值等于 0 的数据对象,即使我知道一个存在。当我在谓词中放置一个断点时,我看到了我永远不会看到的奇怪值,例如 0xCCCC - 可能是未初始化的内存。发生的事情是 reverse_iterator 的取消引用运算符看起来像这样(来自 xutility - Visual Studio 2010)

Data& operator*() const
{   // return designated value
    DataIterator _Tmp = current;
    return (*--_Tmp); //Here's the problem - the * operator on DataIterator returns a value instead of a reference
}

最后一行是问题所在 - 创建临时数据并返回对该数据的引用。该引用立即无效。

如果我将 std::find_if 中的谓词更改为采用 (Data candidate) 而不是 (const Data& candidate),则谓词有效 - 但我很确定我只是幸运地遇到了那里的未定义行为。引用无效,但我正在内存被破坏之前复制数据。

我能做什么?

  1. 修复我的 DataIterator 以便 operator* 返回 Data& 而不是 Data?我真的不明白这怎么可能。我的 DataIterator 返回 Data 而不是 Data& 的全部意义是因为我没有空间在内存中保存整个未压缩的数据集,所以我创建了您想要按需查看的项目。 也许我可以保留“当前”数据值 - 但当您递增或递减 DataIterator 时,该引用将变得无效。 编辑 one of the answers suggests a shared_ptr
  2. 编写一个 reverse_iterator 的特例并让它的取消引用运算符返回一个值而不是一个引用?这看起来是一个令人沮丧的工作量,但可以理解,因为它是我的 DataIterator 在这里表现不佳 - 而不是 STL 的其余部分。
  3. 按照同样的思路,也许做一个反向的 find_if - 可能比专门化 reverse_iterator 工作更少。
  4. 其他我没有想到的

我可以对 DataIterator 做些什么来防止其他人在 6 个月后尝试同样的事情时花半天时间弄清楚问题出在哪里?

最佳答案

并不是说我很喜欢这个想法,但是如果你堆分配了一个 Data 对象,然后返回一个 shared_ptr 的 ref 给它,那会如果需要,允许外界更长时间地捕获它,并让您在向前迈进时“忘记”它。

另一方面,实现您自己的原生 reverse_iterator 可能是一个更大的胜利。这就是我为自己的链表所做的,因为我没有像 gcc 那样使用标记对象,也不能使用 std::reverse_iterator。这真的没有那么难。

关于c++ - 反转按需迭代器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21103664/

相关文章:

c++ - 警告 : non-static data member initializers only available with -std=c++11 or -std=gnu++11?

c++ - 程序在我的机器上运行 2 秒,但在其他机器上运行 15 秒

c++ - 从模板列表中删除对象

c++ - 有哪些 C++ 标准库使用最佳实践?

c++ - 二维数组的自定义迭代器

c++ - 不合格的 ID 和模板类

java - 无法调用我的对象的 iterator() 方法

c++ - 使用套接字与 C++ 中的守护进程交互

c++ - 将复杂的结构/不透明指针/函数从 C++ 头文件转换为 Delphi

algorithm - std::discrete_distribution 接口(interface)背后的原因