[英]Lifetime of lambda objects in relation to function pointer conversion
根據這個答案,我現在想知道lambda的生命周期是什么規則,以及與自動轉換創建的函數指針的生命周期有什么關系。 關於lambdas的生命周期有幾個問題(例如這里和這里 ),在這種情況下,答案是“它們的行為與你自己編寫完整的仿函數對象完全一樣”,但是它們都沒有解決轉換為函數指針的問題。特例。
我把這個小小的工作實例放在一起,說明了我的擔憂:
#include <iostream>
typedef int (*func_t)(int);
// first case
func_t retFun1() {
static auto lambda = [](int) { return 1; };
// automatically converted to func_t
return lambda;
}
// second case
func_t retFun2() {
// no static
auto lambda = [](int) { return 2; };
// automatically converted to func_t and
// the local variable lambda reaches the end of its life
return lambda;
}
int main() {
const int a = retFun1()(0);
const int b = retFun2()(0);
std::cout << a << "," << b << std::endl;
return 0;
}
這兩種情況都有明確定義嗎? 或僅適用於retFun1()
? 問題是:“函數指針指向的函數需要調用函子對象本身,還是在單獨的函數中重新實現正文?” 任何一個都有意義,但事實上轉換為函數指針特別需要一個無捕獲的lambda,這表明它實際上可能是后者。
換句話說 - 我可以看到編譯器可能想要實現這樣的lambda的至少兩種合理方式。 一種可能的合法實現可能是編譯器合成代碼,如:
func_t retFun3() {
struct __voodoo_magic_lambda_implementation {
int operator()(int) const {
return 3;
}
static int plainfunction(int) {
return 3;
}
operator func_t() const {
return plainfunction;
}
} lambda;
return lambda;
}
在這種情況下, retFun
的static
和非static
變體都可以。 但是,如果編譯器實現lambda也是合法的:
static int __voodoo_impl_function(int x);
static struct __voodoo_maigc_impl2 {
int operator()(int) const {
return 4;
}
operator func_t() const {
return __voodoo_impl_function;
}
} *__magic_functor_ptr;
static int __voodoo_impl_function(int x) {
return (*__magic_functor_ptr)(x);
}
func_t retFun4() {
__voodoo_maigc_impl2 lambda;
// non-static, local lifetime
__magic_functor_ptr = λ //Or do the equivalent of this in the ctor
return lambda;
}
然后retFun2()
是未定義的行為。
§5.1.2/ 6說:
沒有lambda-capture的lambda表達式的閉包類型有一個公共的非虛擬非顯式const轉換函數,用於指向具有與閉包類型的函數調用操作符相同的參數和返回類型的函數。 此轉換函數返回的值應為函數的地址,該函數在調用時與調用閉包類型的函數調用運算符具有相同的效果。
強調我的。
換句話說:因為它是函數的地址,而函數沒有生命周期,所以您可以隨時調用該函數。 你擁有的一切都是明確的。
這有點像你做的那樣:
func_t retFun2()
{
int __lambda0(int)
{
return 2;
}
struct
{
int operator(int __arg0) const
{
return __lambda0(__arg0);
}
operator decltype(__lambda0)() const
{
return __lambda0;
}
} lambda;
return lambda; // just the address of a regular ol' function
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.