怎麼正確書寫C++高階函數?
代碼如下,編譯沒錯,運行在最後一行掛掉。
int main(){ std::function&< std::function&( std::function& ) &> f2=[](std::function&
{ std::function&f1) c= [](int param) { return f1(param)*param;
}; return c; }; std::function&f =[](int a){ return a*5;}; std::function&
std::cout&<&<1; f1=f2(f); std::cout&<&<1; std::cout&<&f1; }
你有一個地方不應該引用捕獲,那就是那個高階函數返回lambda的時候
引用捕獲的是函數的局部參數,lambda返回到外面去,引用就失效了
所以記住一條規則,返回到外面的lambda,一律用值捕獲
另外代碼本身也有冗餘,很多地方直接用lambda就好,沒必要用function包一層
#include &
#include &
int main(){
auto f2 = [](auto f1) { //不需要捕獲的地方不要無腦寫
return [=](int param) { //這裡應該值捕獲,因為引用捕獲出了函數體之外就失效了
return f1(param)*param;
};
};
auto f = [](int a){ return a*5;}; //不需要捕獲的地方不要無腦寫
std::cout &<&< 1; auto f1 = f2(f); std::cout &<&< 1; std::cout &<&< f1(1); }
需要C++14
這樣可以嗎?
#include &
#include &
using namespace std;
int main()
{
std::function&
f2 = [](std::function&
{
std::function&
return f1(param) * param;
};
return c;
};
std::function&
std::function&
std::cout &<&< 1;
f1 = f2(f);
std::cout &<&< 1;
if(f2) std::cout &<&< f1(1);
}
C++14 開始按孫明琦菊苣的寫法就行了。
C++11 的話似乎還是要用 std::function 包一下:
#include &
#include &
int main(){
auto f2=[](const std::function&
{
return [=](int param)
{
return f1(param)*param;
};
};
std::function&
auto f1=f2(f); 這裡 f2 的參數直接傳值也可以。 C++14 版本就這個例子來說 f2 參數用傳值更適合。
std::cout&<&
這個確實是因為用了引用捕獲,在
std::function&< std::function&
f2=[](std::function&
{
std::function&
{
return f1(param)*param;
};
return c;
};
這裡,賦給f2的lambda表達式傳入的參數是f1,類型不是引用,是值傳遞,因而在
return f1(param)*param;
這裡返回了一個局部變數。故而報錯。
解決方法之一是這麼寫
std::function&< std::function&
f2 = [](std::function&
{
std::function&
{
return f1(param)*param;
};
return c;
};
注意f2的類型也要有所改變,這或許是題主auto可過的原因,或者如同@kedixa那樣,局部變數c的lambda改為值捕獲。
推薦閱讀:
※你怎麼看 C++11(新的 C++ 標準)裡面的變化?
※我們需不需要跟進C++11/14?
※double 和 long double 有哪些區別?
※C++ 11會帶來什麼影響?