提问人:code_fodder 提问时间:9/30/2020 更新时间:9/30/2020 访问量:93
通过 const std::function 引用传递临时 lambda 应该会失败,但似乎有效
passing a temporary lambda by const std::function reference should fail but seems to work
问:
这是我正在做的事情的简化版本:
#include <iostream>
#include <functional>
class thing
{
public:
void register_fn(const std::function<void()> &fn)
{
m_fn = fn;
}
void run()
{
m_fn();
}
std::function<void()> m_fn;
};
int main() {
// Create a thing object
thing t;
// In a limited scope
{
// Local lambda
auto afn = []{std::cout << "hi\n";};
// Store the lamda by reference
t.register_fn(afn);
}
// Run the stored lambda (which should be destroyed - therefore dangling reference??)
t.run();
// Take a copy
thing t2 = t;
t2.run();
return 0;
}
在此处查看其运行情况:https://godbolt.org/z/6qW3ro
因此,我有一个类来存储通过引用传递的临时 lambda。lamda 的范围是有限的,因此一旦它被传递给寄存器函数,它就会超出范围。然后,在此范围之外,我调用函数,该函数应该运行对 lambda 的(悬空?)引用。afn
run
这一直在工作,但最近回顾我的代码,我有一个疑问。由于 lambda 是临时的(这里通过限制我的 lambda 对象的范围来完成) - 这应该不起作用......我不太明白它为什么会起作用——除非运气好,这是未定义的行为?afn
或。。。我在这里误解了什么?- 因为这可能是最可能的解释!
答:
1赞
NathanOliver
9/30/2020
#1
这主要是因为您制作了函数对象的副本。在
void register_fn(const std::function<void()> &fn)
{
m_fn = fn;
}
你赋给哪个 make a copy 和 即使是对本地 lambda 的引用,make a copy 意味着不引用 ,而是会得到一个函数的副本已经存储在其中。这意味着没有悬空引用,并且您的代码具有明确定义的行为。fn
m_fn
fn
m_fn
fn
fn
如果 lambda 通过引用捕获本地对象,则情况会有所不同,因为在您离开声明 lambda 的作用域后,该捕获将变得无效。
评论
1赞
Deduplicator
9/30/2020
顺便说一句,会更好。void register_fn(std::function<void()> fn) noexcept { m_fn = std::move(fn); }
0赞
code_fodder
9/30/2020
@Deduplicator ah std::function 有一个移动 c'tor - 好点 :)
评论
m_fn = fn;
std::function
std::function