以下代码在 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;
}
这编译得很好,它生成一个异常(不是 header 中定义的logic_error异常)。
如果我更改实现以使用函数而不是仿函数,它就会起作用:
int main()
{
std::deque<int> tests;
std::generate_n( std::back_inserter( tests ), 10, rand );
return 0;
}
这里使用仿函数有什么问题吗?
最佳答案
test_generator
构造函数初始化 value
迭代器以引用 tests
列表中的第一个元素(它是 test_generator 的成员)
)。
当您调用std::generate_n
时,会生成test
的拷贝(因为该对象是按值传递的)。在复制的对象中,value
迭代器引用原始对象中的tests
列表,而不是拷贝。
由于在 Visual Studio STL 实现中执行迭代器调试检查,这会触发断言,因为从一个容器获取的迭代器不应与来自另一容器的迭代器进行比较。
要解决此问题,您可以为 test_generator
类实现复制构造函数,或者将 value
的初始化推迟到第一次 operator()
被调用。
关于c++ - 将自定义仿函数与 std::generate_n() 算法一起使用的正确方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/231198/