我有一个DataIterator
按需生成值的迭代器,因此取消引用运算符返回一个 Data,而不是 Data&。我认为这是一件可以做的事情,直到我尝试通过将数据 DataIterator 包装在 reverse_iterator 中来反转它。
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 的 Data 对象,即使我知道存在一个。当我在谓词中插入断点时,我会看到奇怪的值,这些值我从未想过会看到,例如 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) 则该谓词有效 - 但我很确定我只是对那里未定义的行为感到幸运。引用无效,但我在内存被破坏之前制作了数据的副本。
我能做些什么?
- 修复我的 DataIterator 以便 operator* 返回 Data& 而不是 Data?我真的不明白这怎么可能。我的 DataIterator 返回 Data 而不是 Data& 的全部意义在于我没有空间将整个未压缩数据集保存在内存中,因此我创建了您想要按需查看的项目。
也许我可以保留“当前”数据值 - 但是当您增加或减少 DataIterator 时,该引用将变得无效。编辑 其中一个答案建议使用 shared_ptr - 写一个 reverse_iterator 的特化,让它的解引用操作符返回一个值而不是一个引用?这似乎是一项令人沮丧的工作,但可以理解,因为我的 DataIterator 在这里表现不佳 - 而不是 STL 的其余部分。
- 沿着同样的思路,也许做一个反向的 find_if - 可能比专门化 reverse_iterator 的工作少。
- 其他我没有想到的东西
我可以对 DataIterator 做些什么来防止其他人在 6 个月后尝试同样的事情时花半天时间弄清楚出了什么问题?