Cla*_*diu 15 c++ lambda undefined-behavior c++11
考虑:
std::vector<std::function<void()>> vec;
something_unmovable m;
vec.push_back([&vec, m]() {
vec.resize(100);
// things with 'm'
});
vec[0]();
Run Code Online (Sandbox Code Playgroud)
vec.resize(100)可能会导致向量的重新分配,这意味着std::functions将被复制到一个新位置,而旧的位置将被销毁.然而,当旧的仍在运行时,就会发生这种情况.这个特定的代码运行是因为lambda没有做任何事情,但我想这很容易导致未定义的行为.
那么,究竟发生了什么?是m仍然向量访问?或者是thislambda 的指针现在是无效的(指向释放的内存),因此lambda捕获的任何内容都无法访问,但如果它运行的代码不使用它捕获的任何内容,那么它是不是未定义的行为?
此外,lambda可以移动任何不同的情况?
小智 7
正如其他答案已经涵盖的那样,lambdas本质上是语法糖,可以轻松创建提供自定义operator()实现的类型.这就是为什么你甚至可以使用显式引用来编写lambda调用operator(),如下所示:int main() { return [](){ return 0; }.operator()(); }.所有非静态成员函数的相同规则也适用于lambda主体.
并且这些规则允许在执行成员函数时销毁对象,只要成员函数this之后不使用即可.您的示例是不常见的,更常见的示例是执行非静态成员函数delete this;.这使它成为C++ FAQ,解释说它是允许的.
据我所知,该标准允许这不是真正解决它.它以不依赖于未被销毁的对象的方式描述成员函数的语义,因此实现必须确保即使对象被销毁也要让成员函数继续执行.
那么回答你的问题:
或者是lambda的this指针现在无效(指向释放的内存),因此lambda捕获的任何内容都无法访问,但如果它运行的代码不使用它捕获的任何内容,那么它是不是未定义的行为?
是的,差不多.
此外,lambda可以移动任何不同的情况?
不,这不对.
lambda可移动的唯一时间可能是在lambda移动之后.在你的例子中,operator()继续执行原始的移动 - 然后销毁的仿函数.