【发布时间】:2020-01-31 20:19:17
【问题描述】:
我已经根据此处的答案实现了一个自定义迭代器:
https://stackoverflow.com/a/31886483/1973454
但是,我的代码最终检索存储在某个奇异位置的值,而不是 Type* _ptr 成员,就好像它正在使用以下函数:
// my iterator class gets its values from this function
float globalFloat{ 0 };
float* retrieveFloat (int idx)
{
globalFloat = (float)idx;
return &globalFloat;
}
这意味着为了同时使用两个迭代器(即使用 upper_bound 进行搜索),我必须在允许访问之前在本地缓存浮点数:
class Iterator : public std::iterator<std::random_access_iterator_tag, float, int>
{
public:
Iterator () = default;
Iterator (int idx) : _index (idx) {}
Iterator& operator++ () noexcept { ++_index; return *this; }
Iterator& operator-- () noexcept { --_index; return *this; }
/// ... rest of iterator declaration
const float& operator* () const { _data = *retrieveFloat (_index); return _data; }
const float* operator-> () const { _data = *retrieveFloat (_index); return &this->_data; }
const float& operator[] (int offset) const { _data = *retrieveFloat (_index + offset); return _data; }
private:
int _index{ 0 };
mutable float _data{ 0 };
};
我担心的是最后一个运算符[]。根据cppreference:
https://en.cppreference.com/w/cpp/named_req/RandomAccessIterator
[] 运算符必须返回一个引用类型。但是,如果我要编写以下代码:
int main (int argc, char ** argv)
{
Iterator it;
if (it[0] == it[1])
return 0;
return 1;
}
然后我返回 0,因为每个 [] 调用都会修改 _data。
如果我改变我对 std::iterator 的子类化方式并使用 float 作为我的“参考”类型:
class Iterator : public std::iterator<std::random_access_iterator_tag, float, int, float*, float>
{
public:
/// ... rest of iterator declaration (constructors / operators)
const float operator* () const { _data = *retrieveFloat (_index); return _data; }
const float* operator-> () const { _data = *retrieveFloat (_index); return &this->_data; }
const float operator[] (int offset) const { _data = *retrieveFloat (_index + offset); return _data; }
};
然后一切正常...但不知何故感觉很脏。做这种事情合法吗?
我知道,如果我的数据类型不是浮点数,而是要复制的东西更重,那么就会存在性能问题,但为了论证,假设我只使用浮点数或轻量级 POD。我们还假设我不需要修改被迭代的数据。
感谢您提供的任何帮助,如果我提出这个问题的时间过长,我们深表歉意。如果需要,我可以编辑。
- 约翰
【问题讨论】:
-
这感觉你的迭代器并不能满足成为RandomAccessIterator 的所有要求,也许BidirectionalIterator 可能更合适,这种情况你不必担心
operator[] -
以下也需要工作:
it[1] = 1;。所以[]的返回值不能是副本。 -
我预计您的代码将无法工作,因为例如 std::sort 调用 std::swap 将尝试交换指向相同浮点数的 2 个元素。注意:也许我误解了你的例子。
-
@mynameisjohnj 会提升计数+转换迭代器对您来说是更好的解决方案吗? boost.org/doc/libs/1_72_0/libs/iterator/doc/index.html
-
@NoSenseEtAl 它可能......这值得对不同的迭代器类型进行更多研究。谢谢!