强制将对象作为副本传递给接收通用引用的函数

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

Bar*_*rry 5

如果您阅读以下文档std::bind()您会看到:

返回类型为std::bindstd::decay<F>::type包含构造类型的成员对象std::forward<F>(f)

它不保存对 的引用signal_f,而是保存它的副本。不依赖于生命周期signal_fthis唯一的依赖是捕获的 的生命周期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)

你也可以这样做。