C++11 不存在序列上的迭代器

C++11 不存在序列上的迭代器,c++11,iterator,C++11,Iterator,我有K个对象,K很小,例如2或5,我需要以随机顺序对它们迭代N次,其中N可能很大。我需要在foreach循环中进行迭代,为此我应该提供一个迭代器 到目前为止,我创建了一个std::vector,它对应地复制了K个对象,所以vector的大小是N,现在我使用该向量提供的begin和end。我使用std::shuffle来随机化向量,这占用了20%的运行时间。无论如何,我认为编写一个自定义迭代器,以随机顺序返回我的一个对象,而不创建大小为N的帮助向量,会更好、更优雅。但是如何做到这一点?很明显,迭代

我有K个对象,K很小,例如2或5,我需要以随机顺序对它们迭代N次,其中N可能很大。我需要在foreach循环中进行迭代,为此我应该提供一个迭代器


到目前为止,我创建了一个std::vector,它对应地复制了K个对象,所以vector的大小是N,现在我使用该向量提供的begin和end。我使用std::shuffle来随机化向量,这占用了20%的运行时间。无论如何,我认为编写一个自定义迭代器,以随机顺序返回我的一个对象,而不创建大小为N的帮助向量,会更好、更优雅。但是如何做到这一点?

很明显,迭代器必须:

存储指向原始向量或数组的指针:m_pSource 存储能够停止的请求计数:m_nOutputCount 使用随机数生成器请参见:m_生成器 某些迭代器必须视为结束迭代器:m_nOutputCount==0 我已经为int类型做了一个示例:


您可以轻松地将其转换为模板。并使其接受任何随机访问迭代器。

显然,迭代器必须:

存储指向原始向量或数组的指针:m_pSource 存储能够停止的请求计数:m_nOutputCount 使用随机数生成器请参见:m_生成器 某些迭代器必须视为结束迭代器:m_nOutputCount==0 我已经为int类型做了一个示例:


您可以轻松地将其转换为模板。我只想增加Dmitry的答案,因为阅读你的问题,你似乎希望每次迭代你新创建的和无序的集合时,项目不应该重复,Dmitry的答案确实有重复。所以这两个迭代器都很有用

template <typename T>
struct  RandomIterator : public std::iterator<std::forward_iterator_tag, typename T::value_type>
{
    RandomIterator() : Data(nullptr)
    {
    }

    template <typename G>
    RandomIterator(const T &source, G& g) : Data(&source)
    {
        Order = std::vector<int>(source.size());
        std::iota(begin(Order), end(Order), 0);
        std::shuffle(begin(Order), end(Order), g);
        OrderIterator = begin(Order);
        OrderIteratorEnd = end(Order);
    }

    const typename T::value_type& operator* () const noexcept
    {
        return (*Data)[*OrderIterator];
    }

    RandomIterator<T>& operator++() noexcept
    {
        ++OrderIterator;
        return *this;
    }

    int operator== (const RandomIterator<T>& other) const noexcept
    {
        if (Data == nullptr && other.Data == nullptr)
        {
            return 1;
        }
        else if ((OrderIterator == OrderIteratorEnd) && (other.Data == nullptr))
        {
            return 1;
        }
        return 0;
    }

    int operator!= (const RandomIterator<T>& other) const noexcept
    {
        return !(*this == other);
    }
private:
    const T *Data;
    std::vector<int> Order;
    std::vector<int>::iterator OrderIterator;
    std::vector<int>::iterator OrderIteratorEnd;
};

template <typename T, typename G>
RandomIterator<T> random_begin(const T& v, G& g) noexcept
{
    return RandomIterator<T>(v, g);
}

template <typename T>
RandomIterator<T> random_end(const T& v) noexcept
{
    return RandomIterator<T>();
}
全部代码在 或

实现自定义迭代器可能非常棘手,因此我尝试按照一些教程进行操作,但如果通过了某些操作,请告诉我:

我认为表现令人满意: 关于科里鲁:

<size>:<time for 10 iterations>
1:0.000126582
10:3.5179e-05
100:0.000185914
1000:0.00160409
10000:0.0161338
100000:0.180089
1000000:2.28161
当然,它有价格分配一个完整的向量与订单,这是相同大小的原始向量。
如果出于某种原因,您必须经常随机迭代,并允许迭代器使用此预先分配的向量,或迭代器中的某种形式的重置,则可以预先分配顺序向量。

我只想增加Dmitry答案,因为阅读您的问题,似乎您希望每次迭代新创建的和无序的集合时,这些项都不应该重复,而Dmitryi的答案确实有重复。所以这两个迭代器都很有用

template <typename T>
struct  RandomIterator : public std::iterator<std::forward_iterator_tag, typename T::value_type>
{
    RandomIterator() : Data(nullptr)
    {
    }

    template <typename G>
    RandomIterator(const T &source, G& g) : Data(&source)
    {
        Order = std::vector<int>(source.size());
        std::iota(begin(Order), end(Order), 0);
        std::shuffle(begin(Order), end(Order), g);
        OrderIterator = begin(Order);
        OrderIteratorEnd = end(Order);
    }

    const typename T::value_type& operator* () const noexcept
    {
        return (*Data)[*OrderIterator];
    }

    RandomIterator<T>& operator++() noexcept
    {
        ++OrderIterator;
        return *this;
    }

    int operator== (const RandomIterator<T>& other) const noexcept
    {
        if (Data == nullptr && other.Data == nullptr)
        {
            return 1;
        }
        else if ((OrderIterator == OrderIteratorEnd) && (other.Data == nullptr))
        {
            return 1;
        }
        return 0;
    }

    int operator!= (const RandomIterator<T>& other) const noexcept
    {
        return !(*this == other);
    }
private:
    const T *Data;
    std::vector<int> Order;
    std::vector<int>::iterator OrderIterator;
    std::vector<int>::iterator OrderIteratorEnd;
};

template <typename T, typename G>
RandomIterator<T> random_begin(const T& v, G& g) noexcept
{
    return RandomIterator<T>(v, g);
}

template <typename T>
RandomIterator<T> random_end(const T& v) noexcept
{
    return RandomIterator<T>();
}
全部代码在 或

实现自定义迭代器可能非常棘手,因此我尝试按照一些教程进行操作,但如果通过了某些操作,请告诉我:

我认为表现令人满意: 关于科里鲁:

<size>:<time for 10 iterations>
1:0.000126582
10:3.5179e-05
100:0.000185914
1000:0.00160409
10000:0.0161338
100000:0.180089
1000000:2.28161
当然,它有价格分配一个完整的向量与订单,这是相同大小的原始向量。
如果出于某种原因,您必须经常进行随机迭代,并允许迭代器使用此预先分配的向量,或者在迭代器中进行某种形式的重置,则可以预先分配顺序向量。

如果您希望随机输出每个程序运行。不要忘记使用一些种子初始化m_生成器,例如使用std::random_设备!此外,m_生成器必须是静态的。如果您想要随机输出,请运行每个程序。不要忘记使用一些种子初始化m_生成器,例如使用std::random_设备!此外,m_发电机必须是静态的。