【问题标题】:C++ Return a functor object as std::functionC++ 将仿函数对象作为 std::function 返回
【发布时间】:2020-06-06 19:53:37
【问题描述】:

我有一个工厂方法返回 std::function

class Builder {
public:
    function<void(Data&)> build();
}

和一个仿函数对象

class Processor {
protected:
    vector<int> content_;
public:
    void operator()(Data&) { 
         ....
    }
}

现在我想在工厂方法中返回函子,我写

function<void(Data&)> build() {
    Processor p;
    // Add items to p.content_

    function<void(Data&)> ret(p);

    return ret;
}

我的问题是:ret 会保留一份p 的副本吗?如果是这样,当p.content_ 很大时,这会成为负担吗?建议的实现方式是什么?

【问题讨论】:

  • 使用void operator()(Data&amp;&amp;)function&lt;void(Data&amp;)&gt; ret(std::move(p));。您需要为 Processor 类实现移动构造函数(还记得规则 5)。
  • 嗯.. 合成的移动 ctor 不应该足够吗?零法则!不过,您确实需要返回std::move(ret)
  • @AsteroidsWithWings 从本地移动返回 is implicit
  • 你的代码写得很好(假设你不介意Processor被复制)。事实上,ret 复制了p。您可以使用 function&lt;void(Data&amp;)&gt; ret(std::move(p)) 来移动它
  • @AsteroidsWithWings 我很确定返回值优化会照顾到std::move(ret)

标签: c++ functor std-function


【解决方案1】:

std::function 持有并拥有它的价值。实际上,它需要可复制的可调用对象,以便在复制自身时可以复制它。

你的函数会像这样非常好,并且可能更快:

function<void(Data&)> build() {
    Processor p;

    // fill items

    return p; // p moved into the returned std::function (since C++14)
}

但是,如果您复制 std::function 周围,Processor 对象也会被复制,因此复制 std::function 的成本取决于它包含的类型(就像使用任何类型擦除工具一样)

【讨论】:

  • 感谢您的回答。我还需要对局部变量 p 进行更改(例如,将项目添加到其内容中),所以我需要局部变量存在。
  • @Harper 我刚刚添加了最后一段。希望对你有帮助
【解决方案2】:

将使用的构造函数是this:

template< class F >
function( F f );

您可以看到该对象将被复制。如果你想避免这种情况,你可以移动可调用对象:

function<void(Data&)> ret(std::move(p));

然后构造函数会将f移动到内部存储中。

如果您的可调用对象很小,它将直接存储在函数对象中。如果太大,内部存储将被动态分配。无论哪种方式,移动生成的函数对象应该不会比移动原始可调用对象(直接存储在函数中)更复杂,甚至可能更便宜(动态存储时)。

当性能很重要时应避免复制,因为它可能涉及动态分配,即使您的可调用对象不需要它们。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-06
    • 1970-01-01
    • 1970-01-01
    • 2011-01-04
    相关资源
    最近更新 更多