[英]Passing function object by reference doesn't work in std::generate_n()
我制作了一個用於 std::generate_n 的 FibonacciSeries 仿函數。 但它並沒有按應有的方式工作。 通過引用傳遞函子效果不佳。
在以下程序中 0 1 1 2 3 5 8 13 是預期的 output 但我得到 0 1 1 2 0 1 1 2 作為 output。 有什么問題?
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
inline void printvec(const vector<int>& vec)
{
for (const auto& v : vec)
cout << v << ' ';
cout << endl;
}
class FibonacciSeries
{
private:
int f1;
int f2;
int f3;
public:
FibonacciSeries() :f1(0), f2(1) {}
int operator() () {
f3 = f1 + f2;
int result = f1;
f1 = f2;
f2 = f3;
return result;
}
void printstat(){
cout << f1 << endl;
}
};
int main()
{
vector<int> vec;
FibonacciSeries series;
//passing function object by reference
generate_n<back_insert_iterator<vector<int>>,
int, FibonacciSeries&>(back_inserter(vec), 4, series);
printvec(vec);// prints 0 1 1 2
series.printstat();//prints 0//unexpected
//passing function object by value
generate_n(back_inserter(vec), 4, series);
printvec(vec);//prints 0 1 1 2 0 1 1 2//unexpected
}
我無法重現 gcc 主干( https://godbolt.org/z/PfPPE67h8 )的問題。 但是,標准算法可能會復制內部傳遞給它們的函子。 不確定實現中實際發生了什么“錯誤”,但假設算法以
std::remove_reference<Generator> g = generator;
並使用它來生成 output。 必須閱讀實現以查看導致您的 output 的原因。 但是,使用FibonacciSeries&
作為顯式模板參數是錯誤的方法。 即使生成器是通過引用傳遞的,它也可以在內部復制。
避免您現在觀察到的此類問題的最簡單方法是不要依賴具有 state 的仿函數。 與其讓 state 成為函子的成員,不如讓它通過引用捕獲 state 並將 state 存儲在其他地方。 正如 Sam 在評論中所建議的那樣,使用 Lamba,或者編寫您的自定義包裝器:
struct FibonacciSeriesWrapper {
FibonacciSeries& parent;
int operator() () { return parent(); }
};
int main()
{
vector<int> vec;
FibonacciSeries series;
//passing function object by reference
generate_n(back_inserter(vec), 4, FibonacciSeriesWrapper{series});
generate_n(back_inserter(vec), 4, FibonacciSeriesWrapper{series});
printvec(vec);//prints 0 1 1 2 3 5 8 13
}
您的生成器( FibonnachiSeries
對象)被復制到std::generate_n
調用。 所以原廠 object state 不變。 一種解決方法可能是通過 lambda
generate_n(back_inserter(vec), 4,
[&series] { return series(); });
// UPD:沒關系,將FibonacchiSeries
聲明為參考應該會有所幫助。 你的版本對我來說很好。 你用什么編譯器?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.