如果lambda在运行时被移动/销毁会怎样? [英] What happens if a lambda is moved/destructed while it is running?

查看:67
本文介绍了如果lambda在运行时被移动/销毁会怎样?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑:

  std :: vector< std :: function< void()> vec; 
something_unmovable m;
vec.push_back([& vec,m](){
vec.resize(100);
//带有 m
的事物));
vec [0]();

vec.resize(100)导致重新分配向量,这意味着 std :: function s将被复制到新位置,而旧位置将被销毁。但是,这是在旧版本仍在运行时发生的。运行该特定代码是因为lambda不会执行任何操作,但是我认为这很容易导致未定义的行为。



那么,到底发生了什么?仍然可以从该向量访问 m 吗?还是lambda的 this 指针现在无效(指向已释放的内存),因此lambda捕获的内容无法访问,但是如果它运行的代码不能



另外,lambda可移动的情况是否有所不同?

解决方案

正如其他答案所述,lambda实质上是语法糖,用于轻松创建提供自定义 operator()的类型。实施。这就是为什么您甚至可以使用对 operator()的显式引用编写lambda调用的原因,例如: int main(){return []() {返回0; } .operator()(); } 。对于所有非静态成员函数,相同的规则也适用于lambda主体。



这些规则允许在执行成员函数时销毁对象,只要成员函数此后不使用 this 。您的示例是一个不寻常的示例,更常见的示例是执行的非静态成员函数删除此; 这已成为C ++常见问题解答,解释了允许这样做。据我所知,该标准允许通过不真正解决这一问题来实现这一目标。它以不依赖于不破坏对象的方式描述成员函数的语义,因此实现必须确保即使对象被破坏也要让成员函数继续执行。



所以要回答您的问题:


还是lambda的this指针现在无效(指向已释放的点)内存),因此lambda捕获无法访问,但是,如果运行的代码不使用捕获的任何内容,这不是未定义的行为吗?


是的,差不多。


另外,lambda可移动的情况是否有所不同?


不,不是。



唯一的可移动lambda可能重要的时间是在lambda已被移动。在您的示例中, operator()继续在原始移出然后销毁的函子上执行。


Consider:

std::vector<std::function<void()>> vec;
something_unmovable m;
vec.push_back([&vec, m]() {
    vec.resize(100);
    // things with 'm'
});
vec[0]();

vec.resize(100) will probably cause a re-allocation of the vector, which means that the std::functions will be copied to a new location, and the old ones destroyed. Yet this happens while the old one is still running. This particular code runs because the lambda doesn't do anything, but I imagine this can easily result in undefined behavior.

So, what happens exactly? Is m still accessible from the vector? Or is it that the this pointer of the lambda is now invalid (points to freed memory), so nothing the lambda captures can be accessible, yet if it runs code that doesn't use anything it captures, it's not undefined behavior?

Also, is the case where the lambda is movable any different?

解决方案

As already covered by other answers, lambdas are essentially syntactic sugar for easily creating types that provide a custom operator() implementation. This is why you can even write lambda invocations using an explicit reference to operator(), like so: int main() { return [](){ return 0; }.operator()(); }. The same rules for all non-static member functions also apply to lambda bodies.

And those rules allow the object being destroyed while the member function is being executed, so long as the member function does not use this afterwards. Your example is an unusual one, the more common example is for a non-static member function executing delete this;. This made it into the C++ FAQ, explaining that it's allowed.

The standard allows this by not really addressing it, as far as I am aware. It describes the semantics of member functions in a way that doesn't rely on the object not being destroyed, so implementations must make sure to let member functions continue executing even if the objects get destroyed.

So to answer your questions:

Or is it that the this pointer of the lambda is now invalid (points to freed memory), so nothing the lambda captures can be accessible, yet if it runs code that doesn't use anything it captures, it's not undefined behavior?

Yes, pretty much.

Also, is the case where the lambda is movable any different?

No, it's not.

The only time where the lambda being movable could possibly matter is after the lambda has been moved. In your example, the operator() continues executing on the original moved-from and then destroyed functor.

这篇关于如果lambda在运行时被移动/销毁会怎样?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆