C++ lambda 表达式的生命周期是多少?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7941562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the lifetime of a C++ lambda expression?
提问by
(I have read What is the lifetime of lambda-derived implicit functors in C++?already and it does not answer this question.)
(我已经阅读了 C++ 中 lambda 派生隐式函子的生命周期是什么?已经,它没有回答这个问题。)
I understand that C++ lambda syntax is just sugar for making an instance of an anonymous class with a call operator and some state, and I understand the lifetime requirements of that state (decided by whether you capture by value of by reference.) But what is the lifetime of the lambda object itself? In the following example, is the std::function
instance returned going to be useful?
我知道 C++ lambda 语法只是用于创建带有调用运算符和一些状态的匿名类的实例的糖,并且我了解该状态的生命周期要求(取决于您是否通过引用的值捕获。)但是什么是lambda 对象本身的生命周期?在以下示例中,std::function
返回的实例是否有用?
std::function<int(int)> meta_add(int x) {
auto add = [x](int y) { return x + y; };
return add;
}
If it is, how does it work? This seems a bit too much magic to me - I can only imagine it working by std::function
copying my whole instance, which could be very heavy depending on what I captured - in the past I've used std::function
primarily with bare function pointers, and copying those is quick. It also seems problematic in light of std::function
's type erasure.
如果是,它是如何工作的?这对我来说似乎有点太神奇了 - 我只能想象它通过std::function
复制我的整个实例来工作,这取决于我捕获的内容可能非常繁重 - 过去我std::function
主要使用裸函数指针,复制那些是快的。鉴于std::function
的类型擦除,这似乎也有问题。
采纳答案by Dennis Zickefoose
The lifetime is exactly what it would be if you replaced your lambda with a hand-rolled functor:
如果您将 lambda 替换为手动仿函数,那么生命周期就是这样:
struct lambda {
lambda(int x) : x(x) { }
int operator ()(int y) { return x + y; }
private:
int x;
};
std::function<int(int)> meta_add(int x) {
lambda add(x);
return add;
}
The object will be created, local to the meta_add
function, then moved [in its entirty, including the value of x
] into the return value, then the local instance will go out of scope and be destroyed as normal. But the object returned from the function will remain valid for as long as the std::function
object that holds it does. How long that is obviously depends on the calling context.
对象将被创建,在meta_add
函数的本地,然后将[在其整体中,包括x
]的值移动到返回值中,然后本地实例将超出范围并正常销毁。但是,只要std::function
持有它的对象有效,从函数返回的对象就会一直有效。多长时间显然取决于调用上下文。
回答by deft_code
It seems you're more confused about std::function
than lambdas.
看起来你std::function
比 lambdas更困惑。
std::function
uses a technique called type-erasure. Here's a quick fly by.
std::function
使用一种称为类型擦除的技术。这是一个快速的飞行。
class Base
{
virtual ~Base() {}
virtual int call( float ) =0;
};
template< typename T>
class Eraser : public Base
{
public:
Eraser( T t ) : m_t(t) { }
virtual int call( float f ) override { return m_t(f); }
private:
T m_t;
};
class Erased
{
public:
template<typename T>
Erased( T t ) : m_erased( new Eraser<T>(t) ) { }
int do_call( float f )
{
return m_erased->call( f );
}
private:
Base* m_erased;
};
Why would you want to erase the type? Isn't the type we want just int (*)(float)
?
为什么要擦除类型?不就是我们想要的类型int (*)(float)
吗?
What the type erasure allows is Erased
can now store any value that is callable like int(float)
.
类型擦除允许现在Erased
可以存储任何可调用的值,例如int(float)
.
int boring( float f);
short interesting( double d );
struct Powerful
{
int operator() ( float );
};
Erased e_boring( &boring );
Erased e_interesting( &interesting );
Erased e_powerful( Powerful() );
Erased e_useful( []( float f ) { return 42; } );
回答by Martin York
This is:
这是:
[x](int y) { return x + y; };
Is equivalent to: (Or can be considered too)
相当于:(或者也可以考虑)
struct MyLambda
{
MyLambda(int x): x(x) {}
int operator()(int y) const { return x + y; }
private:
int x;
};
So your object is returning an object that looks just like that. Which has a well defined copy constructor. So it seems very reasonable that it it can be correctly copied out of a function.
所以你的对象正在返回一个看起来像这样的对象。它有一个定义良好的复制构造函数。所以它可以正确地复制出一个函数似乎是非常合理的。
回答by Daniel Trebbien
In the code that you posted:
在您发布的代码中:
std::function<int(int)> meta_add(int x) {
auto add = [x](int y) { return x + y; };
return add;
}
The std::function<int(int)>
object that is returned by the function actually holds a moved instance of the lambda function object that was assigned to local variable add
.
std::function<int(int)>
函数返回的对象实际上保存了分配给局部变量的 lambda 函数对象的移动实例add
。
When you define a C++11 lambda that captures by-value or by-reference, the C++ compiler automatically generates a unique functional type, an instance of which is constructed when the lambda is called or assigned to a variable. To illustrate, your C++ compiler might generate the following class type for the lambda defined by [x](int y) { return x + y; }
:
当您定义捕获按值或按引用的 C++11 lambda 时,C++ 编译器会自动生成唯一的函数类型,在调用 lambda 或将其分配给变量时构造该类型的实例。为了说明这一点,您的 C++ 编译器可能会为由 定义的 lambda 生成以下类类型[x](int y) { return x + y; }
:
class __lambda_373s27a
{
int x;
public:
__lambda_373s27a(int x_)
: x(x_)
{
}
int operator()(int y) const {
return x + y;
}
};
Then, the meta_add
function is essentially equivalent to:
那么,该meta_add
函数本质上等价于:
std::function<int(int)> meta_add(int x) {
__lambda_373s27a add = __lambda_373s27a(x);
return add;
}
EDIT:By the way, I am not sure if you know this, but this is an example of function curryingin C++11.
编辑:顺便说一句,我不确定你是否知道这一点,但这是C++11中函数柯里化的一个例子。