2

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

我的标题看起来像:

#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;

};

我的实现看起来像:

#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;
}

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

如果我将实现更改为使用函数而不是仿函数,它将起作用:

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

    return 0;
}

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

4

2 回答 2

4

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

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

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

要解决这个问题,您可以为您的test_generator类实现一个复制构造函数,或者将初始化推迟value到第一次operator()被调用。

于 2008-10-23T20:18:20.390 回答
0

到目前为止,我还没有弄清楚是什么导致了异常,但你可能希望return *value++在你的operator(). :-)

于 2008-10-23T20:04:40.057 回答