[英]What type of value should it be returned by getters that return size of vector?
[英]What is the return type of a lambda expression if an item of a vector is returned?
請考慮以下代碼段:
#include <iostream>
#include <vector>
#include <functional>
int main()
{
std::vector<int>v = {0,1,2,3,4,5,6};
std::function<const int&(int)> f = [&v](int i) { return v[i];};
std::function<const int&(int)> g = [&v](int i) -> const int& { return v[i];};
std::cout << f(3) << ' ' << g(3) << std::endl;
return 0;
}
我期待相同的結果:在f
, v
由const引用傳遞,因此v[i]
應該具有const int&
type。
但是,我得到了結果
0 3
如果我不使用std :: function,一切都很好:
#include <iostream>
#include <vector>
#include <functional>
int main()
{
std::vector<int>v = {0,1,2,3,4,5,6};
auto f = [&v](int i) { return v[i];};
auto g = [&v](int i) -> const int& { return v[i];};
std::cout << f(3) << ' ' << g(3) << std::endl;
return 0;
}
輸出:
3 3
因此,我想知道:
在第二個片段中,lambda表達式f
的返回類型是什么? 被f
一樣g
?
在第一個片段中,構造std::function f
時發生了什么,導致錯誤?
lambda的返回類型使用auto
返回類型推導規則,它剝離了引用性。 (最初它使用了一組略有不同的規則,這些規則基於左值到右值的轉換(也刪除了引用),但是由DR改變了 。)
因此, [&v](int i) { return v[i];};
返回int
。 因此,在std::function<const int&(int)> f = [&v](int i) { return v[i];};
,調用f()
返回一個懸空引用。 綁定對臨時的引用會延長臨時的生命周期,但在這種情況下綁定發生在std::function
的機器內部,所以在f()
返回時,臨時就已經消失了。
g(3)
很好,因為const int &
return直接綁定到向量元素v[i]
,因此引用永遠不會懸空。
如果返回一個向量項,那么lambda表達式的返回類型是什么?
這是錯誤的問題。
如果沒有明確指定 lambda表達式,你應該問什么是返回類型? 。
答案在C ++ 11 5.1.2 [expr.prim.lambda]第5段中給出,其中它表示lambda是否沒有return expr;
聲明它返回void
,否則:
lvalue-to-rvalue轉換(4.1),數組到指針轉換(4.2)和函數到指針轉換(4.3)之后返回表達式的類型;
(參見下面的TC對DR 1048的評論,它略微改變了這個規則,編譯器實際上實現了更改的規則,但在這種情況下並不重要。)
lvalue-to-rvalue轉換意味着如果return語句返回像v[i]
這樣的左值,它會衰減為rvalue,即它只返回int
值。
所以你的代碼的問題是lambda返回一個臨時的,但是包裝它的std::function<const int&(int)>
綁定了對該臨時的引用。 當您嘗試打印出臨時值已經消失的值(它已經綁定到一個不再存在的堆棧幀的對象),因此您有未定義的行為。
修復是使用std::function<int(int)>
或確保lambda返回有效的引用,而不是rvalue。
在C ++ 14中,非lambdas也可以使用返回類型推導,例如:
auto f(std::vector<int>& v, int i) { return v[i]; }
這遵循與lambda的C ++ 11規則類似(但不完全相同)的規則,因此返回類型為int
。 要返回引用,您需要使用:
decltype(auto) f(std::vector<int>& v, int i) { return v[i]; }
我假設第一個lambda可能返回int
或int&
¹。 不是const int&
因為引用v
不是const對象(捕獲本身不可變是無關緊要的,因為那是引用本身)
當綁定到const-ref時,臨時值的生命周期延伸到封閉范圍的末尾
¹我稍后會嘗試深入研究。 現在,我會定期演繹直覺並說auto
會導致int
,而auto&
會推斷int&
,所以我希望實際的返回類型是int
。 如果有人打敗我,那就更好了。 我幾個小時都沒有時間
請參閱@milleniumbug提供的測試: Live On Coliru
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.