【问题标题】:Force an object to be passed as copy to a function receiving a universal reference强制将对象作为副本传递给接收通用引用的函数
【发布时间】:2016-10-26 17:47:09
【问题描述】:

我正在尝试将本地 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 用于对象而不是容器的版本?

【问题讨论】:

    标签: c++ c++11 lambda stdbind


    【解决方案1】:

    如果您阅读std::bind() 的文档,您会看到:

    std::bind 的返回类型包含一个由std::forward&lt;F&gt;(f) 构造的std::decay&lt;F&gt;::type 类型的成员对象

    它不包含对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));
    

    你也可以这样做。

    【讨论】:

    • 好的,抱歉。我阅读了文档,但我并没有真正“看到”这个词 object(“持有一个成员 object”)。所以,我认为它只是有一个本地的typedefdecay 版本的参数。
    【解决方案2】:

    bind 实际上并不存储对 lambda 的引用。所有参数要么被复制(如果是左值)或者被移动(如果是右值)到bind返回的对象中。

    这就是为什么当可调用对象通过引用获取其参数时,在将参数传递给bind 时需要使用std::ref

    【讨论】:

      猜你喜欢
      • 2011-04-12
      • 1970-01-01
      • 2011-12-07
      • 2019-03-29
      • 1970-01-01
      • 2017-10-18
      • 1970-01-01
      • 2017-08-08
      • 2015-02-05
      相关资源
      最近更新 更多