std::iterator::reference 是否必须是引用?

use*_*454 5 c++ iterator reference

我已经根据这里的答案实现了一个自定义迭代器: 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;
}
Run Code Online (Sandbox Code Playgroud)

这意味着为了同时使用两个迭代器(即使用 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 };
};
Run Code Online (Sandbox Code Playgroud)

我担心的是最后一个运算符[]。根据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;
}
Run Code Online (Sandbox Code Playgroud)

然后我返回 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; }
};
Run Code Online (Sandbox Code Playgroud)

然后事情就可以了……但不知怎的,感觉很脏。做这种事合法吗?

我知道,如果我的数据类型不是浮点数,而是需要更繁重的复制,那么就会出现性能问题,但为了论证起见,我们假设我只使用浮点数或轻量级 POD。我们还假设我不需要修改正在迭代的数据。

感谢您提供的任何帮助,如果我问这个问题太长,我很抱歉。如果需要的话我可以编辑。

  • 约翰

eer*_*ika 5

std::iterator::reference 是否必须是引用?

No.std::iterator::reference不需要是引用类型。它只需要与返回的类型相同operator*并且可以转换为value_type.

但是,为了成为OuputIterator,*r = o必须格式良好,因此reference必须是引用类型或具有非左值引用限定赋值运算符的类类型。因此, usingfloat对于非输出迭代器来说很好,但对于输出迭代器则不好。