2017-08-01 69 views
0

以下代碼給出了分段錯誤。調試完成後,我發現問題可以通過將lambda聲明爲auto而不是Function來解決。爲什麼會這樣?將lambda存儲爲std :: function時出現分段錯誤

#include <functional> 
#include <iostream> 
#include <vector> 

typedef std::vector<double> Vec; 
typedef std::function<const Vec&(Vec)> Function; 


int main() 
{ 
    //Function func = [](const Vec& a)->Vec /*this give me segfault*/ 
    auto func = [](const Vec& a)->Vec /*this work just fine??*/ 
     { 
       Vec b(2); 
       b[0] = a[0] + a[1]; 
       b[1] = a[0] - a[0]; 
       return b; 
     }; 
    Vec b = func(Vec{1,2}); 
    std::cout << b[0] << " " << b[1] << "\n"; 
    return 0; 
} 

這將是巨大的,如果我可以聲明爲功能,因爲我想 這個lambda表達式傳遞給一些其他類。

,我有當func被聲明爲函數是錯誤:

計劃接收信號SIGSEGV,分割過錯。 在std :: vector> :: size(this = 0x0)中的0x0000000000401896在/usr/include/c++/5/bits/stl_vector.h:655 655 {return size_type(this - > _ M_impl._M_finish - this - > _ M_impl。 _M_start); }
(GDB)回溯
#0 0x0000000000401896中的std ::矢量> ::大小(此爲0x0 =)在/usr/include/c++/5/bits/stl_vector.h:655
#1 0x00000000004015aa在std :: vector> :: vector(this = 0x7fffffffdc50,__x =) at /usr/include/c++/5/bits/stl_vector.h:320
#2 0x0000000000400d12 main()at test.cxx:18

回答

6

const Vec&(Vec)相當於看起來像這樣的lambda (Vec) -> const Vec&。你通過(const Vec&) -> Vec

std::function由於包含有效轉換的調用序列(您可以將值傳遞給需要const引用的函數)接受它。

段落錯誤最有可能是您的lambda(臨時)的返回值中固有的未定義行爲綁定到std::functionoperator()中的常量引用;該參考文獻將在std::function之外返回,並立即將其作爲參考。

1

您需要注意函數類型,如果使用正確的函數,它應該可以正常工作;

typedef std::function<Vec(const Vec&)> Function; 

也許問題越清晰,對象包裝和更傳統的功能就越少。

它歸結到,一旦你通過對象刪除間接,是這樣的:

// const Vec& -> Vec 
std::vector<double> the_lambda(const std::vector<double>& x) 
{ 
    return x; 
} 

// Vec -> const Vec& 
const std::vector<double>& the_function(std::vector<double> x) 
{ 
    return the_lambda(x); 
} 


int main() 
{ 
    std::vector<double> v = {1, 2}; 
    std::vector<double> lv = the_lambda(v); // OK. 
    std::vector<double> fv = the_function(v); // Undefined. 
} 

這編譯,但G ++警告說,the_function返回到一個臨時的參考,這與究竟發生了什麼std::function(但沒有太多來自編譯器的提示)。

(我相當確信,允許std::function這種轉換返回值是錯誤的。你不會逃脫它,如果你使用函數指針和C++應該是比安全C,不能少。)