我试图将本地lambda函数传递给std::bind
(用于传递信号的connect
函数):
void f()
{
auto signal_f = [this](int, int) { /* ... */ };
namespace ph = std::placeholders;
signal.connect(std::bind(signal_f, ph::_1, ph::_2));
}
但是std::bind
的函数参数作为通用引用被接收:
template<class F, class... Args>
/* unspecified */ bind(F&& f, Args&&... args);
因此,由于我的lambda对象是一个命名对象,它作为左值引用传递,但我的lambda对象将在f()
存在后被销毁,可能在信号发出时导致内存泄漏。
通过复制传递该对象的最简单方法是什么?
当然,我总能做到这样的事情:
signal.connect(std::bind<std::decay<decltype(signal_f)>::type>
(signal_f, ph::_1, ph::_2));
其他棘手的方法,但它们太麻烦了,那么,最简单的方法是什么?
注意:标准库中是否有任何函数可以创建副本,例如std::make_rvalue(o)
或std::copy
版本的对象而不是容器?
答案 0 :(得分:4)
如果你阅读std::bind()
的文档,你会看到:
std::bind
的返回类型包含从std::decay<F>::type
构建的std::forward<F>(f)
类型的成员对象
它没有对signal_f
的引用,它持有它的副本。不依赖signal_f
的生命周期。唯一的依赖是this
的生命周期,signal_f
捕获。
请注意:
signal.connect(std::bind<std::decay<decltype(signal_f)>::type>(signal_f, ph::_1, ph::_2));
实际上与此相同(decay
没有意义,因为闭包类型不是引用类型):
signal.connect(std::bind<decltype(signal_f)>(signal_f, ph::_1, ph::_2));
实际上与:
相同signal.connect(std::bind(std::move(signal_f), ph::_1, ph::_2));
你也可以这样做。
答案 1 :(得分:3)
bind
实际上并不存储对lambda的引用。所有参数都被复制(如果是左值)或移动(如果是右值)到bind
返回的对象中。
当callable通过引用获取其参数时,这就是为什么在将参数传递给std::ref
时需要使用bind
的原因。