使用std :: generate_n()算法的自定义函子的正确方法?

时间:2022-01-10 22:05:06

The following code compiles correctly under VC++ 8 on XPSP3, but running it causes a runtime error.

以下代码在XPSP3上的VC ++ 8下正确编译,但运行它会导致运行时错误。

My header looks like:

我的标题看起来像:

#include <stdexcept>
#include <iterator>
#include <list>


template<typename T>
class test_generator
{
    public:
    typedef T result_type;

    //constructor
    test_generator()
    {
        std::generate_n( std::back_inserter( tests ), 100, rand );
        value = tests.begin();
    }

    result_type operator()( void )
    {
        if( value == tests.end() )
        {
            throw std::logic_error( "" );
        }

            return *value++;
    }

    private:

    std::list<T> tests;
    typename std::list<T>::iterator value;

};

My implementation looks like:

我的实现看起来像:

#include <functional>
#include <algorithm>
#include <iostream>
#include <deque>

#include "test.h"

int main()
{
    test_generator<double> test;
    std::deque<double> tests;

    std::generate_n( std::back_inserter( tests ), 10, test );

    return 0;
}

This compiles fine, it generates an exception (not the logic_error exception defined in the header).

这编译得很好,它会生成异常(不是标头中定义的logic_error异常)。

If I change the implementation to use a function instead of a functor, it works:

如果我将实现更改为使用函数而不是函数,则它可以工作:

int main()
{
    std::deque<int> tests;
    std::generate_n( std::back_inserter( tests ), 10, rand );

    return 0;
}

What's wrong with using a functor here?

在这里使用仿函数有什么问题?

2 个解决方案

#1


4  

The test_generator constructor initialises the value iterator to reference the first element in the tests list (which is a member of test_generator).

test_generator构造函数初始化值迭代器以引用测试列表中的第一个元素(它是test_generator的成员)。

When you call std::generate_n, a copy of the test is made (because the object is passed by value). In the copied object, the value iterator refers to the tests list in the original object, not the copy.

当您调用std :: generate_n时,会生成一个测试副本(因为该对象是按值传递的)。在复制的对象中,值迭代器引用原始对象中的测试列表,而不是副本。

Because of the iterator debugging checks performed in the Visual Studio STL implementation, this triggers an assertion, because an iterator obtained from one container should not be compared against an iterator from another container.

由于在Visual Studio STL实现中执行迭代器调试检查,这会触发断言,因为从一个容器获取的迭代器不应与另一个容器的迭代器进行比较。

To fix the problem, you could either implement a copy constructor for your test_generator class, or defer initialisation of value until the first time operator() is invoked.

要解决此问题,您可以为test_generator类实现复制构造函数,或者在第一次调用operator()之前推迟初始化值。

#2


0  

I haven't figured out what's causing the exception so far, but you may wish to have return *value++ in your operator(). :-)

到目前为止,我还没有弄清楚导致异常的原因,但您可能希望在operator()中返回* value ++。 :-)

#1


4  

The test_generator constructor initialises the value iterator to reference the first element in the tests list (which is a member of test_generator).

test_generator构造函数初始化值迭代器以引用测试列表中的第一个元素(它是test_generator的成员)。

When you call std::generate_n, a copy of the test is made (because the object is passed by value). In the copied object, the value iterator refers to the tests list in the original object, not the copy.

当您调用std :: generate_n时,会生成一个测试副本(因为该对象是按值传递的)。在复制的对象中,值迭代器引用原始对象中的测试列表,而不是副本。

Because of the iterator debugging checks performed in the Visual Studio STL implementation, this triggers an assertion, because an iterator obtained from one container should not be compared against an iterator from another container.

由于在Visual Studio STL实现中执行迭代器调试检查,这会触发断言,因为从一个容器获取的迭代器不应与另一个容器的迭代器进行比较。

To fix the problem, you could either implement a copy constructor for your test_generator class, or defer initialisation of value until the first time operator() is invoked.

要解决此问题,您可以为test_generator类实现复制构造函数,或者在第一次调用operator()之前推迟初始化值。

#2


0  

I haven't figured out what's causing the exception so far, but you may wish to have return *value++ in your operator(). :-)

到目前为止,我还没有弄清楚导致异常的原因,但您可能希望在operator()中返回* value ++。 :-)