Per*_*-lk 2 c++ lambda stdbind c++11
我正在尝试将本地 lambda 函数传递给 a 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));
}
Run Code Online (Sandbox Code Playgroud)
但 的函数参数std::bind被接收为通用参考:
template<class F, class... Args>
/* unspecified */ bind(F&& f, Args&&... args);
Run Code Online (Sandbox Code Playgroud)
因此,由于我的 lambda 对象是命名对象,因此它作为左值引用传递,但我的 lambda 对象将在存在后被销毁f(),可能会在发出信号时导致内存泄漏。
通过副本传递该对象的最简单方法是什么?
当然,我总是可以做这样的事情:
signal.connect(std::bind<std::decay<decltype(signal_f)>::type>
(signal_f, ph::_1, ph::_2));
Run Code Online (Sandbox Code Playgroud)
还有其他一些棘手的方法,但它们太麻烦了,那么,最简单的方法是什么?
注意:标准库中是否有任何函数可以为对象而不是容器创建副本,例如对象std::make_rvalue(o)或版本?std::copy
如果您阅读以下文档std::bind()您会看到:
返回类型为
std::bindstd::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));
Run Code Online (Sandbox Code Playgroud)
这实际上与此相同(decay是没有意义的,因为闭包类型不是引用类型):
signal.connect(std::bind<decltype(signal_f)>(signal_f, ph::_1, ph::_2));
Run Code Online (Sandbox Code Playgroud)
实际上等同于:
signal.connect(std::bind(std::move(signal_f), ph::_1, ph::_2));
Run Code Online (Sandbox Code Playgroud)
你也可以这样做。