2012-05-13 47 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

謝謝,這是一個優雅的解決方案。 –

相關問題