2012-05-13 45 views
5

我使用下面的结构作为输入到STL的generate_n算法:函子的实例变量不能保持连续的调用之间generate_n

struct GenerateNumber {  
    GenerateNumber() : i(0) {} 
    int operator() (void) {   
     return i++; 
    } 
private: 
    int i; 
}; 

到使用这个仿函数的代码的一个例子是:

std::vector <int> v1 (3); 
std::vector <int> v2 (3); 
GenerateNumber generateNumber; 
std::generate_n (v1.begin(), 3, generateNumber); 
std::generate_n (v2.begin(), 3, generateNumber); 

然而,结果是v1v2都包含{0,1,2},而不是v2以包含{3,4,5}。我已经用断点验证了GenerateNumber的构造函数只被调用过一次(我知道构造函数被多次调用没有意义,但我仍然检查过它)。

我知道我可以通过使i静态来解决这个问题,但我不明白这种行为。连续呼叫之间没有保留i的价值?

回答

8

生成器对象在传递到generate_n时被复制。尝试使用std::ref,即

std::generate_n(v1.begin(), 3, std::ref(generateNumber)); 
std::generate_n(v2.begin(), 3, std::ref(generateNumber)); 

编辑:注意std::ref只在C++ 11提供。它在TR1中被引入为std::tr1::ref,并且也可以在boost::ref中作为提升。

+0

你应该提到'std :: ref'是C++ 11(虽然它在TR1中也有提到)。 –

+0

我可能必须坚持使用'static'解决方案,因为我需要我的代码在VS2010(实现C++ 11)和GCC 4.4(不)的情况下编译。但是,为了完整性,当我使用你的建议时,我得到以下编译错误:'错误C2679:binary'=':找不到操作符的类型为'void'的右操作数(或者没有可接受的转换)\t C:\ Program Files(x86)\ Microsoft Visual Studio 10.0 \ VC \ include \ algorithm \t 1581' –

+0

@LucDanton:谢谢你的提示。有时我会忘记,在C++ 11之前还有一段时间。 – nosid

3

std::generate_n通过值获取仿函数,也就是它复制它。可能是因为您没有检查是否正在调用拷贝构造函数

在没有std::ref,如果你的问题是局部的,如你的榜样,你可以修改你的仿函数采取在通话的范围设定计数器的参考std::generate_n

struct GenerateNumber {  
    GenerateNumber (int& i) : struct GenerateNumber {  
    GenerateNumber() : i(0) {} 
    int operator() (void) {   
     return i++; 
    } 
private: 
    int& i; 
}; 

int main() { 
    int counter = 0; 
    std::vector <int> v1 (3); 
    std::vector <int> v2 (3); 
    GenerateNumber generateNumber(counter); 
    std::generate_n (v1.begin(), 3, generateNumber); 
    std::generate_n (v2.begin(), 3, generateNumber); 

} 
+0

谢谢,这是一个优雅的解决方案。 –

相关问题