我有一个工厂方法返回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_
大时,这会成为负担吗?建议的实现方式是什么?
A 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
的成本取决于其包含的类型(就像使用任何类型擦除工具一样)
将使用的构造函数为this:
template< class F >
function( F f );
您可以看到该对象将被复制。如果要避免这种情况,可以移动可调用对象:
function<void(Data&)> ret(std::move(p));
然后构造函数将f
移至内部存储器。
如果您的可调用项很小,它将直接存储在函数对象中。如果太大,内部存储将动态分配。无论哪种方式,移动结果函数对象都不应比移动原始可调用对象(当直接存储在函数中时)复杂,甚至可能更便宜(当动态存储时)。
当性能很重要时,应避免复制,因为即使您的可调用对象不需要动态分配,它也可能涉及动态分配。